diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2016-01-26 21:10:49 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2016-01-26 21:10:49 +0000 |
| commit | 6694780c2d02d645f053fd60864c9ff035296a64 (patch) | |
| tree | fd205fc40c3b1b0aa432bbc1bdbe2c78f3d1c60b /src/drivers/GDI | |
| parent | ac275b89bcd8333dd1b05bfc9f6fc0accd8e065d (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.h | 116 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx | 64 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx | 247 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx | 612 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx | 66 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx | 239 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx | 127 |
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 = ⟼ + 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 = ⟼ + 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$". +// |
