summaryrefslogtreecommitdiff
path: root/src/drivers/GDI
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2016-01-26 21:10:49 +0000
committerMatthias Melcher <fltk@matthiasm.com>2016-01-26 21:10:49 +0000
commit6694780c2d02d645f053fd60864c9ff035296a64 (patch)
treefd205fc40c3b1b0aa432bbc1bdbe2c78f3d1c60b /src/drivers/GDI
parentac275b89bcd8333dd1b05bfc9f6fc0accd8e065d (diff)
Moving GDI/WIN32 files to new directroy structure
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11058 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers/GDI')
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.h116
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx64
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx247
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx612
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx66
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx239
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx127
7 files changed, 1471 insertions, 0 deletions
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h
new file mode 100644
index 000000000..c38b23a5c
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h
@@ -0,0 +1,116 @@
+//
+// "$Id$"
+//
+// Definition of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
+// for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2010-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+/**
+ \file gdi.h
+ \brief Definition of MSWindows GDI graphics driver.
+ */
+
+#ifndef FL_CFG_GFX_GDI_H
+#define FL_CFG_GFX_GDI_H
+
+#include <FL/Fl_Device.H>
+
+
+/**
+ \brief The MSWindows-specific graphics class.
+ *
+ This class is implemented only on the MSWindows platform.
+ */
+class FL_EXPORT Fl_GDI_Graphics_Driver : public Fl_Graphics_Driver {
+protected:
+ int numcount;
+ int counts[20];
+public:
+ static const char *class_id;
+ const char *class_name() {return class_id;};
+ void draw(const char* str, int n, int x, int y);
+ void draw(int angle, const char *str, int n, int x, int y);
+ void rtl_draw(const char* str, int n, int x, int y);
+ void font(Fl_Font face, Fl_Fontsize size);
+ void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+ void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+ void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+ void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+ double width(const char *str, int n);
+ double width(unsigned int c);
+ void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
+ int height();
+ int descent();
+#if ! defined(FL_DOXYGEN)
+ 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);
+protected:
+ // --- 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);
+ // --- clipping
+ void push_clip(int x, int y, int w, int h);
+ int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
+ int not_clipped(int x, int y, int w, int h);
+ void push_no_clip();
+ void pop_clip();
+ void restore_clip();
+ // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
+ void begin_complex_polygon();
+ void transformed_vertex(double xf, double yf);
+ void vertex(double x, double y);
+ void end_points();
+ void end_line();
+ void end_loop();
+ void end_polygon();
+ void end_complex_polygon();
+ void gap();
+ void circle(double x, double y, double r);
+ // --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
+ // using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
+ // --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
+ void arc(int x, int y, int w, int h, double a1, double a2);
+ void pie(int x, int y, int w, int h, double a1, double a2);
+ // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
+ void line_style(int style, int width=0, char* dashes=0);
+ // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+ void color(Fl_Color c);
+ Fl_Color color() { return color_; }
+ void color(uchar r, uchar g, uchar b);
+};
+
+
+#endif // FL_CFG_GFX_GDI_H
+
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
new file mode 100644
index 000000000..9a16e14e8
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
@@ -0,0 +1,64 @@
+//
+// "$Id$"
+//
+// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#ifndef FL_CFG_GFX_GDI_ARCI_CXX
+#define FL_CFG_GFX_GDI_ARCI_CXX
+
+/**
+ \file gdi_arci.cxx
+ \brief Utility functions for drawing circles using integers
+*/
+
+#include "Fl_GDI_Graphics_Driver.h"
+
+#include <FL/math.h>
+
+void Fl_GDI_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+ if (w <= 0 || h <= 0) return;
+ int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
+ int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
+ int xb = x+w/2+int(w*cos(a2/180.0*M_PI));
+ int yb = y+h/2-int(h*sin(a2/180.0*M_PI));
+ if (fabs(a1 - a2) < 90) {
+ if (xa == xb && ya == yb) SetPixel(fl_gc, xa, ya, fl_RGB());
+ else Arc(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+ } else Arc(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+}
+
+void Fl_GDI_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
+ if (w <= 0 || h <= 0) return;
+ if (a1 == a2) return;
+ int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
+ int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
+ int xb = x+w/2+int(w*cos(a2/180.0*M_PI));
+ int yb = y+h/2-int(h*sin(a2/180.0*M_PI));
+ SelectObject(fl_gc, fl_brush());
+ if (fabs(a1 - a2) < 90) {
+ if (xa == xb && ya == yb) {
+ MoveToEx(fl_gc, x+w/2, y+h/2, 0L);
+ LineTo(fl_gc, xa, ya);
+ SetPixel(fl_gc, xa, ya, fl_RGB());
+ } else Pie(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+ } else Pie(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb);
+}
+
+#endif // FL_CFG_GFX_GDI_ARCI_CXX
+
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx
new file mode 100644
index 000000000..2113b13b5
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx
@@ -0,0 +1,247 @@
+//
+// "$Id$"
+//
+// MSWidnows' GDI color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+// The fltk "colormap". This allows ui colors to be stored in 8-bit
+// locations, and provides a level of indirection so that global color
+// changes can be made. Not to be confused with the X colormap, which
+// I try to hide completely.
+
+#include "Fl_GDI_Graphics_Driver.h"
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+// FIXME: all the global functions in this file should probably be protected
+// members of the driver class. Starting with 1.4 we will allow multiple drivers
+// to co-exist, creating conflicts with multipe mapping.
+
+// FIXME: maybe we can forget about color mapping and assume RGB?
+
+static unsigned fl_cmap[256] = {
+#include "../../fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+// Translations to win32 data structures:
+Fl_XMap fl_xmap[256];
+
+Fl_XMap* fl_current_xmap;
+
+HPALETTE fl_palette;
+static HGDIOBJ tmppen=0;
+static HPEN savepen=0;
+
+void fl_cleanup_pens(void) {
+ for (int i=0; i<256; i++) {
+ if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen);
+ }
+}
+
+void fl_save_pen(void) {
+ if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0);
+ savepen = (HPEN)SelectObject(fl_gc, tmppen);
+}
+
+void fl_restore_pen(void) {
+ if (savepen) SelectObject(fl_gc, savepen);
+ DeleteObject(tmppen);
+ tmppen = 0;
+ savepen = 0;
+}
+
+static void clear_xmap(Fl_XMap& xmap) {
+ if (xmap.pen) {
+ HGDIOBJ tmppen = GetStockObject(BLACK_PEN);
+ HGDIOBJ oldpen = SelectObject(fl_gc, tmppen); // Push out the current pen of the gc
+ if(oldpen != xmap.pen) SelectObject(fl_gc, oldpen); // Put it back if it is not the one we are about to delete
+ DeleteObject((HGDIOBJ)(xmap.pen));
+ xmap.pen = 0;
+ xmap.brush = -1;
+ }
+}
+
+static void set_xmap(Fl_XMap& xmap, COLORREF c) {
+ xmap.rgb = c;
+ if (xmap.pen) {
+ HGDIOBJ oldpen = SelectObject(fl_gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one
+ if (oldpen != xmap.pen)SelectObject(fl_gc,oldpen); // if old one not xmap.pen, need to put it back
+ DeleteObject(xmap.pen); // delete pen
+ }
+ xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen
+ xmap.brush = -1;
+}
+
+void Fl_GDI_Graphics_Driver::color(Fl_Color i) {
+ if (i & 0xffffff00) {
+ unsigned rgb = (unsigned)i;
+ fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
+ } else {
+ Fl_Graphics_Driver::color(i);
+ Fl_XMap &xmap = fl_xmap[i];
+ if (!xmap.pen) {
+#if USE_COLORMAP
+ if (fl_palette) {
+ set_xmap(xmap, PALETTEINDEX(i));
+ } else {
+#endif
+ unsigned c = fl_cmap[i];
+ set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)));
+#if USE_COLORMAP
+ }
+#endif
+ }
+ fl_current_xmap = &xmap;
+ SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+ }
+}
+
+void Fl_GDI_Graphics_Driver::color(uchar r, uchar g, uchar b) {
+ static Fl_XMap xmap;
+ COLORREF c = RGB(r,g,b);
+ Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
+ if (!xmap.pen || c != xmap.rgb) {
+ clear_xmap(xmap);
+ set_xmap(xmap, c);
+ }
+ fl_current_xmap = &xmap;
+ SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+}
+
+HBRUSH fl_brush() {
+ return fl_brush_action(0);
+}
+
+HBRUSH fl_brush_action(int action) {
+ Fl_XMap *xmap = fl_current_xmap;
+ // Wonko: we use some statistics to cache only a limited number
+ // of brushes:
+#define FL_N_BRUSH 16
+ static struct Fl_Brush {
+ HBRUSH brush;
+ unsigned short usage;
+ Fl_XMap* backref;
+ } brushes[FL_N_BRUSH];
+
+ if (action) {
+ SelectObject(fl_gc, GetStockObject(BLACK_BRUSH)); // Load stock object
+ for (int i=0; i<FL_N_BRUSH; i++) {
+ if (brushes[i].brush)
+ DeleteObject(brushes[i].brush); // delete all brushes in array
+ }
+ return NULL;
+ }
+
+ int i = xmap->brush; // find the associated brush
+ if (i != -1) { // if the brush was allready allocated
+ if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+ if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
+ for (int j=0; j<FL_N_BRUSH; j++) {
+ if (brushes[j].usage>16000)
+ brushes[j].usage -= 16000;
+ else
+ brushes[j].usage = 0;
+ }
+ }
+ return brushes[i].brush;
+ } else {
+ int umin = 32000, imin = 0;
+ for (i=0; i<FL_N_BRUSH; i++) {
+ if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+ if (brushes[i].usage<umin) {
+ umin = brushes[i].usage;
+ imin = i;
+ }
+ }
+ i = imin;
+ HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH); // get a stock brush
+ HGDIOBJ oldbrush = SelectObject(fl_gc,tmpbrush); // load in into current context
+ if (oldbrush != brushes[i].brush) SelectObject(fl_gc,oldbrush); // reload old one
+ DeleteObject(brushes[i].brush); // delete the one in list
+ brushes[i].brush = NULL;
+ brushes[i].backref->brush = -1;
+ }
+CREATE_BRUSH:
+ brushes[i].brush = CreateSolidBrush(xmap->rgb);
+ brushes[i].usage = 0;
+ brushes[i].backref = xmap;
+ xmap->brush = i;
+ return brushes[i].brush;
+}
+
+void Fl::free_color(Fl_Color i, int overlay) {
+ if (overlay) return; // do something about GL overlay?
+ clear_xmap(fl_xmap[i]);
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ clear_xmap(fl_xmap[i]);
+ fl_cmap[i] = c;
+ }
+}
+
+#if USE_COLORMAP
+
+// 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
+// Thanks to Michael Sweet @ Easy Software Products for this
+
+HPALETTE
+fl_select_palette(void)
+{
+ static char beenhere;
+ if (!beenhere) {
+ beenhere = 1;
+
+ //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL;
+ int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE);
+ if (nColors <= 0 || nColors > 256) return NULL;
+ // this will try to work on < 256 color screens, but will probably
+ // come out quite badly.
+
+ // I lamely try to get this variable-sized object allocated on stack:
+ ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
+ LOGPALETTE *pPal = (LOGPALETTE*)foo;
+
+ pPal->palVersion = 0x300;
+ pPal->palNumEntries = nColors;
+
+ // Build 256 colors from the standard FLTK colormap...
+
+ for (int i = 0; i < nColors; i ++) {
+ pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255;
+ pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
+ pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255;
+ pPal->palPalEntry[i].peFlags = 0;
+ };
+
+ // Create the palette:
+ fl_palette = CreatePalette(pPal);
+ }
+ if (fl_palette) {
+ SelectPalette(fl_gc, fl_palette, FALSE);
+ RealizePalette(fl_gc);
+ }
+ return fl_palette;
+}
+
+#endif
+
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
new file mode 100644
index 000000000..6f2504391
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
@@ -0,0 +1,612 @@
+//
+// "$Id$"
+//
+// WIN32 font utilities for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2010 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+// This function fills in the FLTK font table with all the fonts that
+// are found on the X server. It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+#include <FL/fl_utf8.h>
+#ifdef __CYGWIN__
+# include <wchar.h>
+#endif
+
+// Bug: older versions calculated the value for *ap as a side effect of
+// making the name, and then forgot about it. To avoid having to change
+// the header files I decided to store this value in the last character
+// of the font name array.
+#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
+
+// turn a stored font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+ Fl_Fontdesc *f = fl_fonts + fnum;
+ if (!f->fontname[0]) {
+ const char* p = f->name;
+ if (!p || !*p) {if (ap) *ap = 0; return "";}
+ int type;
+ switch (*p) {
+ case 'B': type = FL_BOLD; break;
+ case 'I': type = FL_ITALIC; break;
+ case 'P': type = FL_BOLD | FL_ITALIC; break;
+ default: type = 0; break;
+ }
+ strlcpy(f->fontname, p+1, ENDOFBUFFER);
+ if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
+ if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
+ f->fontname[ENDOFBUFFER] = (char)type;
+ }
+ if (ap) *ap = f->fontname[ENDOFBUFFER];
+ return f->fontname;
+}
+
+static int fl_free_font = FL_FREE_FONT;
+
+static int CALLBACK
+enumcbw(CONST LOGFONTW *lpelf,
+ CONST TEXTMETRICW * /*lpntm*/,
+ DWORD /*FontType*/,
+ LPARAM p) {
+ if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1;
+ char *n = NULL;
+ size_t l = wcslen(lpelf->lfFaceName);
+ unsigned dstlen = fl_utf8fromwc(n, 0, (xchar*)lpelf->lfFaceName, (unsigned) l) + 1; // measure the string
+ n = (char*) malloc(dstlen);
+//n[fl_unicode2utf((xchar*)lpelf->lfFaceName, l, n)] = 0;
+ dstlen = fl_utf8fromwc(n, dstlen, (xchar*)lpelf->lfFaceName, (unsigned) l); // convert the string
+ n[dstlen] = 0;
+ for (int i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts
+ if (!strcmp(Fl::get_font_name((Fl_Font)i),n)) {free(n);return 1;}
+ char buffer[LF_FACESIZE + 1];
+ strcpy(buffer+1, n);
+ buffer[0] = ' '; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ if (lpelf->lfWeight <= 400)
+ buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ if (lpelf->lfWeight <= 400)
+ buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+ free(n);
+ return 1;
+} /* enumcbw */
+
+Fl_Font Fl::set_fonts(const char* xstarname) {
+ if (fl_free_font == FL_FREE_FONT) {// if not already been called
+ if (!fl_gc) fl_GetDC(0);
+
+ EnumFontFamiliesW(fl_gc, NULL, (FONTENUMPROCW)enumcbw, xstarname != 0);
+
+ }
+ return (Fl_Font)fl_free_font;
+}
+
+
+static int nbSize;
+static int cyPerInch;
+static int sizes[128];
+static int CALLBACK
+
+EnumSizeCbW(CONST LOGFONTW * /*lpelf*/,
+ CONST TEXTMETRICW *lpntm,
+ DWORD fontType,
+ LPARAM /*p*/) {
+ if ((fontType & RASTER_FONTTYPE) == 0) {
+ sizes[0] = 0;
+ nbSize = 1;
+
+ // Scalable font
+ return 0;
+ }
+
+ int add = lpntm->tmHeight - lpntm->tmInternalLeading;
+ add = MulDiv(add, 72, cyPerInch);
+
+ int start = 0;
+ while ((start < nbSize) && (sizes[start] < add)) {
+ start++;
+ }
+
+ if ((start < nbSize) && (sizes[start] == add)) {
+ return 1;
+ }
+
+ for (int i=nbSize; i>start; i--) sizes[i] = sizes[i - 1];
+
+ sizes[start] = add;
+ nbSize++;
+
+ // Stop enum if buffer overflow
+ return nbSize < 128;
+}
+
+
+int
+Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+ nbSize = 0;
+ Fl_Fontdesc *s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+
+ if (!fl_gc) fl_GetDC(0);
+ cyPerInch = GetDeviceCaps(fl_gc, LOGPIXELSY);
+ if (cyPerInch < 1) cyPerInch = 1;
+
+// int l = fl_utf_nb_char((unsigned char*)s->name+1, strlen(s->name+1));
+// unsigned short *b = (unsigned short*) malloc((l + 1) * sizeof(short));
+// fl_utf2unicode((unsigned char*)s->name+1, l, (xchar*)b);
+ const char *nm = (const char*)s->name+1;
+ size_t len = strlen(s->name+1);
+ unsigned l = fl_utf8toUtf16(nm, (unsigned) len, NULL, 0); // Pass NULL to query length required
+ unsigned short *b = (unsigned short*) malloc((l + 1) * sizeof(short));
+ l = fl_utf8toUtf16(nm, (unsigned) len, b, (l+1)); // Now do the conversion
+ b[l] = 0;
+ EnumFontFamiliesW(fl_gc, (WCHAR*)b, (FONTENUMPROCW)EnumSizeCbW, 0);
+ free(b);
+
+ sizep = sizes;
+ return nbSize;
+}
+
+
+//
+// End of "$Id$".
+//
+//
+// "$Id$"
+//
+// WIN32 font selection routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2012 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#include <FL/Fl_Printer.H>
+
+static int fl_angle_ = 0;
+
+#ifndef FL_DOXYGEN
+Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize) {
+ int weight = FW_NORMAL;
+ int italic = 0;
+ switch (*name++) {
+ case 'I': italic = 1; break;
+ case 'P': italic = 1;
+ case 'B': weight = FW_BOLD; break;
+ case ' ': break;
+ default: name--;
+ }
+ fid = CreateFont(
+ -fsize, // negative makes it use "char size"
+ 0, // logical average character width
+ fl_angle_*10, // angle of escapement
+ fl_angle_*10, // base-line orientation angle
+ weight,
+ italic,
+ FALSE, // underline attribute flag
+ FALSE, // strikeout attribute flag
+ DEFAULT_CHARSET, // character set identifier
+ OUT_DEFAULT_PRECIS, // output precision
+ CLIP_DEFAULT_PRECIS,// clipping precision
+ DEFAULT_QUALITY, // output quality
+ DEFAULT_PITCH, // pitch and family
+ name // pointer to typeface name string
+ );
+ angle = fl_angle_;
+ if (!fl_gc) fl_GetDC(0);
+ SelectObject(fl_gc, fid);
+ GetTextMetrics(fl_gc, &metr);
+// BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar);
+// ...would be the right call, but is not implemented into Window95! (WinNT?)
+ //GetCharWidth(fl_gc, 0, 255, width);
+ int i;
+ memset(width, 0, 64 * sizeof(int*));
+#if HAVE_GL
+ listbase = 0;
+ for (i = 0; i < 64; i++) glok[i] = 0;
+#endif
+ size = fsize;
+}
+
+Fl_Font_Descriptor::~Fl_Font_Descriptor() {
+#if HAVE_GL
+// Delete list created by gl_draw(). This is not done by this code
+// as it will link in GL unnecessarily. There should be some kind
+// of "free" routine pointer, or a subclass?
+// if (listbase) {
+// int base = font->min_char_or_byte2;
+// int size = font->max_char_or_byte2-base+1;
+// int base = 0; int size = 256;
+// glDeleteLists(listbase+base,size);
+// }
+#endif
+ if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
+ DeleteObject(fid);
+ for (int i = 0; i < 64; i++) {
+ if ( width[i] ) free(width[i]);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+// WARNING: if you add to this table, you must redefine FL_FREE_FONT
+// in Enumerations.H & recompile!!
+static Fl_Fontdesc built_in_table[] = {
+{" Arial"},
+{"BArial"},
+{"IArial"},
+{"PArial"},
+{" Courier New"},
+{"BCourier New"},
+{"ICourier New"},
+{"PCourier New"},
+{" Times New Roman"},
+{"BTimes New Roman"},
+{"ITimes New Roman"},
+{"PTimes New Roman"},
+{" Symbol"},
+{" Terminal"},
+{"BTerminal"},
+{" Wingdings"},
+};
+
+Fl_Fontdesc* fl_fonts = built_in_table;
+
+static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) {
+ Fl_Fontdesc* s = fl_fonts+fnum;
+ if (!s->name) s = fl_fonts; // use 0 if fnum undefined
+ Fl_Font_Descriptor* f;
+ for (f = s->first; f; f = f->next)
+ if (f->size == size && f->angle == angle) return f;
+ f = new Fl_Font_Descriptor(s->name, size);
+ f->next = s->first;
+ s->first = f;
+ return f;
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+static void fl_font(Fl_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
+ if (fnum==-1) { // just make sure that we will load a new font next time
+ fl_angle_ = 0;
+ driver->Fl_Graphics_Driver::font(0, 0);
+ return;
+ }
+ if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && angle == fl_angle_) return;
+ fl_angle_ = angle;
+ driver->Fl_Graphics_Driver::font(fnum, size);
+ driver->font_descriptor( find(fnum, size, angle) );
+}
+
+void Fl_GDI_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+ fl_font(this, fnum, size, 0);
+}
+
+int Fl_GDI_Graphics_Driver::height() {
+ Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+ if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
+ else return -1;
+}
+
+int Fl_GDI_Graphics_Driver::descent() {
+ Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+ if (fl_fontsize) return fl_fontsize->metr.tmDescent;
+ else return -1;
+}
+
+// Unicode string buffer
+static unsigned short *wstr = NULL;
+static int wstr_len = 0;
+
+
+double Fl_GDI_Graphics_Driver::width(const char* c, int n) {
+ int i = 0;
+ if (!font_descriptor()) return -1.0;
+ double w = 0.0;
+ char *end = (char *)&c[n];
+ while (i < n) {
+ unsigned int ucs;
+ int l;
+ ucs = fl_utf8decode((const char*)(c + i), end, &l);
+// if (l < 1) l = 1;
+ i += l;
+ if (!fl_nonspacing(ucs)) {
+ w += width(ucs);
+ }
+ }
+ return w;
+}
+
+double Fl_GDI_Graphics_Driver::width(unsigned int c) {
+ Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+ unsigned int r;
+ SIZE s;
+ // Special Case Handling of Unicode points over U+FFFF.
+ // The logic (below) computes a lookup table for char widths
+ // on-the-fly, but the table only covers codepoints up to
+ // U+FFFF, which covers the basic multilingual plane, but
+ // not any higher plane, or glyphs that require surrogate-pairs
+ // to encode them in WinXX, which is UTF16.
+ // This code assumes that these glyphs are rarely used and simply
+ // measures them explicitly if they occur - This will be slow...
+ if(c > 0x0000FFFF) { // UTF16 surrogate pair is needed
+ if (!fl_gc) { // We have no valid gc, so nothing to measure - bail out
+ return 0.0;
+ }
+ int cc; // cell count
+ unsigned short u16[4]; // Array for UTF16 representation of c
+ // Creates a UTF16 string from a UCS code point.
+ cc = fl_ucs_to_Utf16(c, u16, 4);
+ // Make sure the current font is selected before we make the measurement
+ SelectObject(fl_gc, fl_fontsize->fid);
+ // measure the glyph width
+ GetTextExtentPoint32W(fl_gc, (WCHAR*)u16, cc, &s);
+ return (double)s.cx;
+ }
+ // else - this falls through to the lookup-table for glyph widths
+ // in the basic multilingual plane
+ r = (c & 0xFC00) >> 10;
+ if (!fl_fontsize->width[r]) {
+ fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400);
+ for (int i = 0; i < 0x0400; i++) fl_fontsize->width[r][i] = -1;
+ } else {
+ if ( fl_fontsize->width[r][c&0x03FF] >= 0 ) { // already cached
+ return (double) fl_fontsize->width[r][c & 0x03FF];
+ }
+ }
+ unsigned short ii = r * 0x400;
+ // The following code makes a best effort attempt to obtain a valid fl_gc.
+ // If no fl_gc is available at the time we call fl_width(), then we first
+ // try to obtain a gc from the first fltk window.
+ // If that is null then we attempt to obtain the gc from the current screen
+ // using (GetDC(NULL)).
+ // This should resolve STR #2086
+ HDC gc = fl_gc;
+ HWND hWnd = 0;
+ if (!gc) { // We have no valid gc, try and obtain one
+ // Use our first fltk window, or fallback to using the screen via GetDC(NULL)
+ hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL;
+ gc = GetDC(hWnd);
+ }
+ if (!gc) Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!");
+ SelectObject(gc, fl_fontsize->fid);
+ ii += c &0x03FF;
+ GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s);
+ fl_fontsize->width[r][c&0x03FF] = s.cx;
+ if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc);
+ return (double) fl_fontsize->width[r][c & 0x03FF];
+}
+
+/* Add function pointer to allow us to access GetGlyphIndicesW on systems that have it,
+ * without crashing on systems that do not. */
+/* DWORD WINAPI GetGlyphIndicesW(HDC,LPCWSTR,int,LPWORD,DWORD) */
+typedef DWORD (WINAPI* fl_GetGlyphIndices_func)(HDC,LPCWSTR,int,LPWORD,DWORD);
+
+static fl_GetGlyphIndices_func fl_GetGlyphIndices = NULL; // used to hold a proc pointer for GetGlyphIndicesW
+static int have_loaded_GetGlyphIndices = 0; // Set this non-zero once we have tried to load GetGlyphIndices
+
+// Function that tries to dynamically load GetGlyphIndicesW at runtime
+static void GetGlyphIndices_init() {
+ // Since not all versions of Windows include GetGlyphIndicesW support,
+ // we do a run-time check for the required function.
+ HMODULE hMod = GetModuleHandle("GDI32.DLL");
+ if (hMod) {
+ // check that GetGlyphIndicesW is available
+ fl_GetGlyphIndices = (fl_GetGlyphIndices_func)GetProcAddress(hMod, "GetGlyphIndicesW");
+ }
+ have_loaded_GetGlyphIndices = -1; // set this non-zero when we have attempted to load GetGlyphIndicesW
+} // GetGlyphIndices_init function
+
+static void on_printer_extents_update(int &dx, int &dy, int &w, int &h)
+// converts text extents from device coords to logical coords
+{
+ POINT pt[3] = { {0, 0}, {dx, dy}, {dx+w, dy+h} };
+ DPtoLP(fl_gc, pt, 3);
+ w = pt[2].x - pt[1].x;
+ h = pt[2].y - pt[1].y;
+ dx = pt[1].x - pt[0].x;
+ dy = pt[1].y - pt[0].y;
+}
+
+// if printer context, extents shd be converted to logical coords
+#define EXTENTS_UPDATE(x,y,w,h) \
+ if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { on_printer_extents_update(x,y,w,h); }
+
+// Function to determine the extent of the "inked" area of the glyphs in a string
+void Fl_GDI_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
+
+ Fl_Font_Descriptor *fl_fontsize = font_descriptor();
+ if (!fl_fontsize) { // no valid font, nothing to measure
+ w = 0; h = 0;
+ dx = dy = 0;
+ return;
+ }
+
+ static unsigned short *ext_buff = NULL; // UTF-16 converted version of input UTF-8 string
+ static WORD *w_buff = NULL; // glyph indices array
+ static unsigned wc_len = 0; // current string buffer dimensions
+ static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; // identity mat for GetGlyphOutlineW
+ GLYPHMETRICS metrics;
+ int maxw = 0, maxh = 0, dh;
+ int minx = 0, miny = -999999;
+ unsigned len = 0, idx = 0;
+ HWND hWnd = 0;
+ HDC gc = fl_gc; // local copy of current gc - make a copy in case we change it...
+ int has_surrogates; // will be set if the string contains surrogate pairs
+
+ // Have we loaded the GetGlyphIndicesW function yet?
+ if (have_loaded_GetGlyphIndices == 0) {
+ GetGlyphIndices_init();
+ }
+ // Do we have a usable GetGlyphIndices function?
+ if(!fl_GetGlyphIndices) goto exit_error; // No GetGlyphIndices function, use fallback mechanism instead
+
+ // The following code makes a best effort attempt to obtain a valid fl_gc.
+ // See description in fl_width() above for an explanation.
+ if (!gc) { // We have no valid gc, try and obtain one
+ // Use our first fltk window, or fallback to using the screen via GetDC(NULL)
+ hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL;
+ gc = GetDC(hWnd);
+ }
+ if (!gc) goto exit_error; // no valid gc, attempt to use fallback measure
+
+ // now convert the string to WCHAR and measure it
+ len = fl_utf8toUtf16(c, n, ext_buff, wc_len);
+ if(len >= wc_len) {
+ if(ext_buff) {delete [] ext_buff;}
+ if(w_buff) {delete [] w_buff;}
+ wc_len = len + 64;
+ ext_buff = new unsigned short[wc_len];
+ w_buff = new WORD[wc_len];
+ len = fl_utf8toUtf16(c, n, ext_buff, wc_len);
+ }
+ SelectObject(gc, fl_fontsize->fid);
+
+ // Are there surrogate-pairs in this string? If so GetGlyphIndicesW will fail
+ // since it can only handle the BMP range.
+ // We ideally want to use GetGlyphIndicesW, as it is the Right Thing, but it
+ // only works for the BMP, so we leverage GetCharacterPlacementW instead, which
+ // is not ideal, but works adequately well, and does handle surrogate pairs.
+ has_surrogates = 0;
+ for(unsigned ll = 0; ll < len; ll++) {
+ if((ext_buff[ll] >= 0xD800) && (ext_buff[ll] < 0xE000)) {
+ has_surrogates = -1;
+ break;
+ }
+ }
+ if (has_surrogates) {
+ // GetGlyphIndices will not work - use GetCharacterPlacementW() instead
+ GCP_RESULTSW gcp_res;
+ memset(w_buff, 0, (sizeof(WORD) * wc_len));
+ memset(&gcp_res, 0, sizeof(GCP_RESULTSW));
+ gcp_res.lpGlyphs = (LPWSTR)w_buff;
+ gcp_res.nGlyphs = wc_len;
+ gcp_res.lStructSize = sizeof(gcp_res);
+
+ DWORD dr = GetCharacterPlacementW(gc, (WCHAR*)ext_buff, len, 0, &gcp_res, GCP_GLYPHSHAPE);
+ if(dr) {
+ len = gcp_res.nGlyphs;
+ } else goto exit_error;
+ } else {
+ if (fl_GetGlyphIndices(gc, (WCHAR*)ext_buff, len, w_buff, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) {
+ // some error occured here - just return fl_measure values
+ goto exit_error;
+ }
+ }
+
+ // now we have the glyph array we measure each glyph in turn...
+ for(idx = 0; idx < len; idx++){
+ if (GetGlyphOutlineW (gc, w_buff[idx], GGO_METRICS | GGO_GLYPH_INDEX,
+ &metrics, 0, NULL, &matrix) == GDI_ERROR) {
+ goto exit_error;
+ }
+ maxw += metrics.gmCellIncX;
+ if(idx == 0) minx = metrics.gmptGlyphOrigin.x;
+ dh = metrics.gmBlackBoxY - metrics.gmptGlyphOrigin.y;
+ if(dh > maxh) maxh = dh;
+ if(miny < metrics.gmptGlyphOrigin.y) miny = metrics.gmptGlyphOrigin.y;
+ }
+ // for the last cell, we only want the bounding X-extent, not the glyphs increment step
+ maxw = maxw - metrics.gmCellIncX + metrics.gmBlackBoxX + metrics.gmptGlyphOrigin.x;
+ w = maxw - minx;
+ h = maxh + miny;
+ dx = minx;
+ dy = -miny;
+ EXTENTS_UPDATE(dx, dy, w, h);
+ return; // normal exit
+
+exit_error:
+ // some error here - just return fl_measure values
+ w = (int)width(c, n);
+ h = height();
+ dx = 0;
+ dy = descent() - h;
+ EXTENTS_UPDATE(dx, dy, w, h);
+ return;
+} // fl_text_extents
+
+void Fl_GDI_Graphics_Driver::draw(const char* str, int n, int x, int y) {
+ COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
+ // avoid crash if no font has been set yet
+ if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
+ SelectObject(fl_gc, font_descriptor()->fid);
+ int wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
+ if(wn >= wstr_len) {
+ wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
+ wstr_len = wn + 1;
+ wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
+ }
+ TextOutW(fl_gc, x, y, (WCHAR*)wstr, wn);
+ SetTextColor(fl_gc, oldColor); // restore initial state
+}
+
+void Fl_GDI_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) {
+ fl_font(this, Fl_Graphics_Driver::font(), size(), angle);
+ int wn = 0; // count of UTF16 cells to render full string
+ COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
+ SelectObject(fl_gc, font_descriptor()->fid);
+ wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
+ if(wn >= wstr_len) { // Array too small
+ wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
+ wstr_len = wn + 1;
+ wn = fl_utf8toUtf16(str, n, wstr, wstr_len); // respin the translation
+ }
+ TextOutW(fl_gc, x, y, (WCHAR*)wstr, wn);
+ SetTextColor(fl_gc, oldColor);
+ fl_font(this, Fl_Graphics_Driver::font(), size(), 0);
+}
+
+void Fl_GDI_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+ int wn;
+ wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
+ if(wn >= wstr_len) {
+ wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
+ wstr_len = wn + 1;
+ wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
+ }
+
+ COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
+ SelectObject(fl_gc, font_descriptor()->fid);
+#ifdef RTL_CHAR_BY_CHAR
+ int i = 0;
+ int lx = 0;
+ while (i < wn) { // output char by char is very bad for Arabic but coherent with fl_width()
+ lx = (int) width(wstr[i]);
+ x -= lx;
+ TextOutW(fl_gc, x, y, (WCHAR*)wstr + i, 1);
+ if (fl_nonspacing(wstr[i])) {
+ x += lx;
+ }
+ i++;
+ }
+#else
+ UINT old_align = SetTextAlign(fl_gc, TA_RIGHT | TA_RTLREADING);
+ TextOutW(fl_gc, x, y - height() + descent(), (WCHAR*)wstr, wn);
+ SetTextAlign(fl_gc, old_align);
+#endif
+ SetTextColor(fl_gc, oldColor);
+}
+#endif
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
new file mode 100644
index 000000000..cd84aae0a
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
@@ -0,0 +1,66 @@
+//
+// "$Id$"
+//
+// Line style code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#ifndef FL_CFG_GFX_GDI_LINE_STYLE_CXX
+#define FL_CFG_GFX_GDI_LINE_STYLE_CXX
+
+/**
+ \file gdi_line_style.cxx
+ \brief Line style drawing utility hiding different platforms.
+*/
+
+#include "Fl_GDI_Graphics_Driver.h"
+
+
+void Fl_GDI_Graphics_Driver::line_style(int style, int width, char* dashes) {
+
+ // save line width in global variable for X11 clipping
+ if (width == 0) fl_line_width_ = 1;
+ else fl_line_width_ = width>0 ? width : -width;
+
+ // According to Bill, the "default" cap and join should be the
+ // "fastest" mode supported for the platform. I don't know why
+ // they should be different (same graphics cards, etc., right?) MRS
+ static DWORD Cap[4]= {PS_ENDCAP_FLAT, PS_ENDCAP_FLAT, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE};
+ static DWORD Join[4]={PS_JOIN_ROUND, PS_JOIN_MITER, PS_JOIN_ROUND, PS_JOIN_BEVEL};
+ int s1 = PS_GEOMETRIC | Cap[(style>>8)&3] | Join[(style>>12)&3];
+ DWORD a[16]; int n = 0;
+ if (dashes && dashes[0]) {
+ s1 |= PS_USERSTYLE;
+ for (n = 0; n < 16 && *dashes; n++) a[n] = *dashes++;
+ } else {
+ s1 |= style & 0xff; // allow them to pass any low 8 bits for style
+ }
+ if ((style || n) && !width) width = 1; // fix cards that do nothing for 0?
+ LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()?
+ HPEN newpen = ExtCreatePen(s1, width, &penbrush, n, n ? a : 0);
+ if (!newpen) {
+ Fl::error("fl_line_style(): Could not create GDI pen object.");
+ return;
+ }
+ HPEN oldpen = (HPEN)SelectObject(fl_gc, newpen);
+ DeleteObject(oldpen);
+ DeleteObject(fl_current_xmap->pen);
+ fl_current_xmap->pen = newpen;
+}
+
+#endif // FL_CFG_GFX_GDI_LINE_STYLE_CXX
+
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
new file mode 100644
index 000000000..5adb0056d
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
@@ -0,0 +1,239 @@
+//
+// "$Id$"
+//
+// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#ifndef FL_CFG_GFX_QUARTZ_RECT_CXX
+#define FL_CFG_GFX_QUARTZ_RECT_CXX
+
+
+/**
+ \file gdi_rect.cxx
+ \brief MSWindows GDI specific line and polygon drawing with integer coordinates.
+ */
+
+#include "Fl_GDI_Graphics_Driver.h"
+
+
+// --- line and polygon drawing with integer coordinates
+
+void Fl_GDI_Graphics_Driver::point(int x, int y) {
+ SetPixel(fl_gc, x, y, fl_RGB());
+}
+
+void Fl_GDI_Graphics_Driver::rect(int x, int y, int w, int h) {
+ if (w<=0 || h<=0) return;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x+w-1, y);
+ LineTo(fl_gc, x+w-1, y+h-1);
+ LineTo(fl_gc, x, y+h-1);
+ LineTo(fl_gc, x, y);
+}
+
+void Fl_GDI_Graphics_Driver::rectf(int x, int y, int w, int h) {
+ if (w<=0 || h<=0) return;
+ RECT rect;
+ rect.left = x; rect.top = y;
+ rect.right = x + w; rect.bottom = y + 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<y1) y3--;
+ else y3++;
+ MoveToEx(fl_gc, x, y, 0L);
+ LineTo(fl_gc, x, y1);
+ LineTo(fl_gc, x2, y1);
+ LineTo(fl_gc, x2, y3);
+}
+
+void Fl_GDI_Graphics_Driver::loop(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);
+ LineTo(fl_gc, x, y);
+}
+
+void Fl_GDI_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+ 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);
+}
+
+void Fl_GDI_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
+ 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;
+ SelectObject(fl_gc, fl_brush());
+ Polygon(fl_gc, p, 3);
+}
+
+void Fl_GDI_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+ 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 = x3; p[3].y = y3;
+ SelectObject(fl_gc, fl_brush());
+ Polygon(fl_gc, p, 4);
+}
+
+// --- clipping
+
+void Fl_GDI_Graphics_Driver::push_clip(int x, int y, int w, int h) {
+ Fl_Region r;
+ if (w > 0 && h > 0) {
+ r = XRectangleRegion(x,y,w,h);
+ Fl_Region current = rstack[rstackptr];
+ if (current) {
+ CombineRgn(r,r,current,RGN_AND);
+ }
+ } else { // make empty clip region:
+ r = CreateRectRgn(0,0,0,0);
+ }
+ if (rstackptr < region_stack_max) rstack[++rstackptr] = r;
+ else Fl::warning("Fl_GDI_Graphics_Driver::push_clip: clip stack overflow!\n");
+ fl_restore_clip();
+}
+
+int Fl_GDI_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
+ X = x; Y = y; W = w; H = h;
+ Fl_Region r = rstack[rstackptr];
+ if (!r) return 0;
+ // The win32 API makes no distinction between partial and complete
+ // intersection, so we have to check for partial intersection ourselves.
+ // However, given that the regions may be composite, we have to do
+ // some voodoo stuff...
+ Fl_Region rr = XRectangleRegion(x,y,w,h);
+ Fl_Region temp = CreateRectRgn(0,0,0,0);
+ int ret;
+ if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint
+ W = H = 0;
+ ret = 2;
+ } else if (EqualRgn(temp, rr)) { // complete
+ ret = 0;
+ } else { // partial intersection
+ RECT rect;
+ GetRgnBox(temp, &rect);
+ if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if print context, convert coords from device to logical
+ POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} };
+ DPtoLP(fl_gc, pt, 2);
+ X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y;
+ }
+ else {
+ X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
+ }
+ ret = 1;
+ }
+ DeleteObject(temp);
+ DeleteObject(rr);
+ return ret;
+}
+
+int Fl_GDI_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
+ if (x+w <= 0 || y+h <= 0) return 0;
+ Fl_Region r = rstack[rstackptr];
+ if (!r) return 1;
+ RECT rect;
+ if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // in case of print context, convert coords from logical to device
+ POINT pt[2] = { {x, y}, {x + w, y + h} };
+ LPtoDP(fl_gc, pt, 2);
+ rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y;
+ } else {
+ rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
+ }
+ return RectInRegion(r,&rect);
+}
+
+// make there be no clip (used by fl_begin_offscreen() only!)
+void Fl_GDI_Graphics_Driver::push_no_clip() {
+ if (rstackptr < region_stack_max) rstack[++rstackptr] = 0;
+ else Fl::warning("Fl_GDI_Graphics_Driver::push_no_clip: clip stack overflow!\n");
+ fl_restore_clip();
+}
+
+// pop back to previous clip:
+void Fl_GDI_Graphics_Driver::pop_clip() {
+ if (rstackptr > 0) {
+ Fl_Region oldr = rstack[rstackptr--];
+ if (oldr) XDestroyRegion(oldr);
+ } else Fl::warning("Fl_GDI_Graphics_Driver::pop_clip: clip stack underflow!\n");
+ fl_restore_clip();
+}
+
+void Fl_GDI_Graphics_Driver::restore_clip() {
+ fl_clip_state_number++;
+ Fl_Region r = rstack[rstackptr];
+ SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared
+}
+
+
+#endif // FL_CFG_GFX_GDI_RECT_CXX
+
+//
+// End of "$Id$".
+//
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
new file mode 100644
index 000000000..ee12c9ad8
--- /dev/null
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
@@ -0,0 +1,127 @@
+//
+// "$Id$"
+//
+// Portable drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#ifndef FL_CFG_GFX_GDI_VERTEX_CXX
+#define FL_CFG_GFX_GDI_VERTEX_CXX
+
+/**
+ \file gdi_vertex.cxx
+ \brief Portable drawing code for drawing arbitrary shapes with
+ simple 2D transformations, implemented for MSWindows GDI.
+ */
+
+#include "Fl_GDI_Graphics_Driver.h"
+
+#include <FL/fl_draw.H>
+#include <FL/x.H>
+#include <FL/math.h>
+
+
+void Fl_GDI_Graphics_Driver::transformed_vertex(double xf, double yf) {
+ transformed_vertex0(COORD_T(rint(xf)), COORD_T(rint(yf)));
+}
+
+void Fl_GDI_Graphics_Driver::vertex(double x,double y) {
+ transformed_vertex0(COORD_T(x*m.a + y*m.c + m.x), COORD_T(x*m.b + y*m.d + m.y));
+}
+
+void Fl_GDI_Graphics_Driver::end_points() {
+ for (int i=0; i<n; i++) SetPixel(fl_gc, p[i].x, p[i].y, fl_RGB());
+}
+
+void Fl_GDI_Graphics_Driver::end_line() {
+ if (n < 2) {
+ end_points();
+ return;
+ }
+ if (n>1) Polyline(fl_gc, p, n);
+}
+
+void Fl_GDI_Graphics_Driver::end_loop() {
+ fixloop();
+ if (n>2) transformed_vertex((COORD_T)p[0].x, (COORD_T)p[0].y);
+ end_line();
+}
+
+void Fl_GDI_Graphics_Driver::end_polygon() {
+ fixloop();
+ if (n < 3) {
+ end_line();
+ return;
+ }
+ if (n>2) {
+ SelectObject(fl_gc, fl_brush());
+ Polygon(fl_gc, p, n);
+ }
+}
+
+void Fl_GDI_Graphics_Driver::begin_complex_polygon() {
+ begin_polygon();
+ gap_ = 0;
+ numcount = 0;
+}
+
+void Fl_GDI_Graphics_Driver::gap() {
+ while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--;
+ if (n > gap_+2) {
+ transformed_vertex((COORD_T)p[gap_].x, (COORD_T)p[gap_].y);
+ counts[numcount++] = n-gap_;
+ gap_ = n;
+ } else {
+ n = gap_;
+ }
+}
+
+void Fl_GDI_Graphics_Driver::end_complex_polygon() {
+ gap();
+ if (n < 3) {
+ end_line();
+ return;
+ }
+ if (n>2) {
+ SelectObject(fl_gc, fl_brush());
+ PolyPolygon(fl_gc, p, counts, numcount);
+ }
+}
+
+// shortcut the closed circles so they use XDrawArc:
+// warning: these do not draw rotated ellipses correctly!
+// See fl_arc.c for portable version.
+
+void Fl_GDI_Graphics_Driver::circle(double x, double y,double 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;
+
+ if (what==POLYGON) {
+ SelectObject(fl_gc, fl_brush());
+ Pie(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0);
+ } else
+ Arc(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0);
+}
+
+#endif // FL_CFG_GFX_GDI_VERTEX_CXX
+
+//
+// End of "$Id$".
+//