diff options
Diffstat (limited to 'src/drivers/GDI')
| -rw-r--r-- | src/drivers/GDI/Fl_Font.H | 43 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H | 35 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx | 95 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.H | 230 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx | 322 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx | 89 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx | 259 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx | 678 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 826 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx | 111 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx | 320 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx | 231 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H | 44 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx | 169 |
14 files changed, 0 insertions, 3452 deletions
diff --git a/src/drivers/GDI/Fl_Font.H b/src/drivers/GDI/Fl_Font.H deleted file mode 100644 index 3e8b1296f..000000000 --- a/src/drivers/GDI/Fl_Font.H +++ /dev/null @@ -1,43 +0,0 @@ -// -// Font definitions for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -// Two internal fltk data structures: -// -// Fl_Fontdesc: an entry into the fl_font() table. There is one of these -// for each fltk font number. -// -#ifndef FL_FONT_ -#define FL_FONT_ - -#include <config.h> -#include "../../Fl_Scalable_Graphics_Driver.H" - -class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor { -public: - HFONT fid; - int *width[64]; - TEXTMETRIC metr; - int angle; - FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size); -# if HAVE_GL - char glok[64]; -# endif // HAVE_GL - virtual FL_EXPORT ~Fl_GDI_Font_Descriptor(); -}; - -extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table - -#endif diff --git a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H deleted file mode 100644 index 7eae4c2bc..000000000 --- a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). -// -// Copyright 2022 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -#ifndef FL_GDI_COPY_SURFACE_DRIVER_H -#define FL_GDI_COPY_SURFACE_DRIVER_H - -#include <FL/Fl_Copy_Surface.H> -#include <FL/platform.H> - -class Fl_GDI_Copy_Surface_Driver : public Fl_Copy_Surface_Driver { - friend class Fl_Copy_Surface_Driver; -protected: - HDC oldgc; - HDC gc; - Fl_GDI_Copy_Surface_Driver(int w, int h); - ~Fl_GDI_Copy_Surface_Driver(); - void set_current() FL_OVERRIDE; - void translate(int x, int y) FL_OVERRIDE; - void untranslate() FL_OVERRIDE; -}; - -#endif // FL_GDI_COPY_SURFACE_DRIVER_H diff --git a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx deleted file mode 100644 index c44c0a77b..000000000 --- a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -#include <config.h> -#include "Fl_GDI_Copy_Surface_Driver.H" -#include <FL/platform.H> -#include "Fl_GDI_Graphics_Driver.H" -#include "../WinAPI/Fl_WinAPI_Screen_Driver.H" -#include <FL/Fl_Image_Surface.H> -#include <windows.h> - - -Fl_GDI_Copy_Surface_Driver::Fl_GDI_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { - driver(Fl_Graphics_Driver::newMainGraphicsDriver()); - oldgc = (HDC)Fl_Surface_Device::surface()->driver()->gc(); - // exact computation of factor from screen units to EnhMetaFile units (0.01 mm) - HDC hdc = GetDC(NULL); - int hmm = GetDeviceCaps(hdc, HORZSIZE); - int hdots = GetDeviceCaps(hdc, HORZRES); - int vmm = GetDeviceCaps(hdc, VERTSIZE); - int vdots = GetDeviceCaps(hdc, VERTRES); - ReleaseDC(NULL, hdc); - float factorw = (100.f * hmm) / hdots; - float factorh = (100.f * vmm) / vdots; - // Global display scaling factor: 1, 1.25, 1.5, 1.75, etc... - float scaling = Fl_Graphics_Driver::default_driver().scale(); - driver()->scale(scaling); - RECT rect; rect.left = 0; rect.top = 0; rect.right = (LONG)((w*scaling) * factorw); rect.bottom = (LONG)((h*scaling) * factorh); - gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL); - if (gc != NULL) { - SetTextAlign(gc, TA_BASELINE|TA_LEFT); - SetBkMode(gc, TRANSPARENT); - } -} - - -Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() { - if (oldgc == (HDC)Fl_Surface_Device::surface()->driver()->gc()) oldgc = NULL; - HENHMETAFILE hmf = CloseEnhMetaFile (gc); - if ( hmf != NULL ) { - if ( OpenClipboard (NULL) ){ - EmptyClipboard (); - // put first the vectorial form of the graphics in the clipboard - SetClipboardData (CF_ENHMETAFILE, hmf); - // then put a BITMAP version of the graphics in the clipboard - float scaling = driver()->scale(); - int W = Fl_Scalable_Graphics_Driver::floor(width, scaling), H = Fl_Scalable_Graphics_Driver::floor(height, scaling); - RECT rect = {0, 0, W, H}; - Fl_Image_Surface *surf = new Fl_Image_Surface(W, H); - Fl_Surface_Device::push_current(surf); - fl_color(FL_WHITE); // draw white background - fl_rectf(0, 0, W, H); - PlayEnhMetaFile((HDC)surf->driver()->gc(), hmf, &rect); // draw metafile to offscreen buffer - SetClipboardData(CF_BITMAP, (HBITMAP)surf->offscreen()); - Fl_Surface_Device::pop_current(); - delete surf; - - CloseClipboard (); - } - DeleteEnhMetaFile(hmf); - } - DeleteDC(gc); - Fl_Surface_Device::surface()->driver()->gc(oldgc); - delete driver(); -} - - -void Fl_GDI_Copy_Surface_Driver::set_current() { - driver()->gc(gc); - fl_window = (HWND)1; - Fl_Surface_Device::set_current(); -} - - -void Fl_GDI_Copy_Surface_Driver::translate(int x, int y) { - ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y); -} - - -void Fl_GDI_Copy_Surface_Driver::untranslate() { - ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all(); -} diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H deleted file mode 100644 index 336fa1ebc..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H +++ /dev/null @@ -1,230 +0,0 @@ -// -// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device -// for the Fast Light Tool Kit (FLTK). -// -// Copyright 2010-2023 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -/** - \file Fl_GDI_Graphics_Driver.H - \brief Definition of Windows GDI graphics driver. - */ - -#ifndef FL_GDI_GRAPHICS_DRIVER_H -#define FL_GDI_GRAPHICS_DRIVER_H - -#include "../../Fl_Scalable_Graphics_Driver.H" -#include <windows.h> -#include <stdlib.h> -#include <config.h> - -#if USE_GDIPLUS -# if defined(_MSC_VER) -# include <objidl.h> -# else -# include <wtypes.h> // for PROPID needed with gcc 4.9.0 but not with 4.9.3 -# endif -# include <gdiplus.h> -#endif - -/** - \brief The Windows-specific graphics driver class. - - This class is implemented only on the Windows platform. -*/ -class Fl_GDI_Graphics_Driver : public Fl_Scalable_Graphics_Driver { -private: - BOOL alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch); - int depth; // to support translation - POINT *origins; // to support translation - void set_current_() FL_OVERRIDE; - void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void draw_fixed(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void make_unused_color_(unsigned char &r, unsigned char &g, unsigned char &b, int color_count, void **data) FL_OVERRIDE; -protected: - void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void cache(Fl_RGB_Image *rgb) FL_OVERRIDE; - HDC gc_; - int numcount; - int counts[20]; - uchar *mask_bitmap_; - uchar **mask_bitmap() FL_OVERRIDE {return &mask_bitmap_;} - POINT *long_point; - int style_; -public: - Fl_GDI_Graphics_Driver(); - ~Fl_GDI_Graphics_Driver() FL_OVERRIDE; - int has_feature(driver_feature mask) FL_OVERRIDE { return mask & NATIVE; } - char can_do_alpha_blending() FL_OVERRIDE; - void gc(void *ctxt) FL_OVERRIDE { gc_ = (HDC)ctxt; global_gc(); } - void *gc() FL_OVERRIDE {return gc_;} - - // --- bitmap stuff - static HBITMAP create_bitmask(int w, int h, const uchar *array); // NOT virtual - static HBITMAP calc_HBITMAP_mask(Fl_RGB_Image *mask); - void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE; - HBITMAP create_alphamask(int w, int h, int d, int ld, const uchar *array); - void draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE; - void draw_unscaled(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; - void rtl_draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE; - void font_unscaled(Fl_Font face, Fl_Fontsize size) FL_OVERRIDE; - void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) FL_OVERRIDE; - void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) FL_OVERRIDE; - void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) FL_OVERRIDE; - void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) FL_OVERRIDE; - void cache(Fl_Pixmap *img) FL_OVERRIDE; - void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE; - void cache(Fl_Bitmap *img) FL_OVERRIDE; - void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE; - double width_unscaled(const char *str, int n) FL_OVERRIDE; - double width_unscaled(unsigned int c) FL_OVERRIDE; - void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; - int height_unscaled() FL_OVERRIDE; - int descent_unscaled() FL_OVERRIDE; - Fl_Fontsize size_unscaled() FL_OVERRIDE; -#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) FL_OVERRIDE; - void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) FL_OVERRIDE; - Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE; - void XDestroyRegion(Fl_Region r) FL_OVERRIDE; - void translate_all(int x, int y); - void untranslate_all(void); - static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr); - void scale(float f) FL_OVERRIDE; - float scale() {return Fl_Graphics_Driver::scale();} -protected: - void transformed_vertex0(float x, float y) FL_OVERRIDE; - void fixloop() FL_OVERRIDE; - void point(int x, int y) FL_OVERRIDE; - void focus_rect(int x, int y, int w, int h) FL_OVERRIDE; - void rect_unscaled(int x, int y, int w, int h) FL_OVERRIDE; - void rectf_unscaled(int x, int y, int w, int h) FL_OVERRIDE; -#if USE_COLORMAP - void colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) FL_OVERRIDE; -#endif - void line_unscaled(int x, int y, int x1, int y1) FL_OVERRIDE; - void line_unscaled(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; - void xyline_unscaled(int x, int y, int x1) FL_OVERRIDE; - void yxline_unscaled(int x, int y, int y1) FL_OVERRIDE; - void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; - void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; - void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; - void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; - // --- clipping - void push_clip(int x, int y, int w, int h) FL_OVERRIDE; - int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; - int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; - void restore_clip() FL_OVERRIDE; - Fl_Region scale_clip(float f) FL_OVERRIDE; - // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx - void begin_complex_polygon() FL_OVERRIDE; - void end_points() FL_OVERRIDE; - void end_line() FL_OVERRIDE; - void end_loop() FL_OVERRIDE; - void end_polygon() FL_OVERRIDE; - void end_complex_polygon() FL_OVERRIDE; - void gap() FL_OVERRIDE; - void ellipse_unscaled(double xt, double yt, double rx, double ry) FL_OVERRIDE; - void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; - void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; - void line_style_unscaled(int style, int width, char* dashes) FL_OVERRIDE; - void color(Fl_Color c) FL_OVERRIDE; - Fl_Color color() FL_OVERRIDE { return color_; } - void color(uchar r, uchar g, uchar b) FL_OVERRIDE; - void set_color(Fl_Color i, unsigned int c) FL_OVERRIDE; - void free_color(Fl_Color i, int overlay) FL_OVERRIDE; - Fl_Font set_fonts(const char *name) FL_OVERRIDE; - int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE; - const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE; - const char *font_name(int num) FL_OVERRIDE; - void font_name(int num, const char *name) FL_OVERRIDE; - void global_gc() FL_OVERRIDE; - void overlay_rect(int x, int y, int w , int h) FL_OVERRIDE; - void cache_size(Fl_Image *img, int &width, int &height) FL_OVERRIDE; - void* change_pen_width(int width) FL_OVERRIDE; - void reset_pen_width(void *data) FL_OVERRIDE; -}; - - -/** - The graphics driver used when printing on Windows. - - This class is implemented only on the Windows platform. - It is extremely similar to Fl_GDI_Graphics_Driver. -*/ -class Fl_GDI_Printer_Graphics_Driver : public Fl_GDI_Graphics_Driver { -private: - typedef BOOL (WINAPI* transparent_f_type) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); - transparent_f_type TransparentBlt(); -public: - int has_feature(driver_feature mask) FL_OVERRIDE { return mask & (NATIVE | PRINTER); } - void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; - void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) FL_OVERRIDE; -}; - -#if USE_GDIPLUS - -class Fl_GDIplus_Graphics_Driver : public Fl_GDI_Graphics_Driver { - friend class Fl_Graphics_Driver; -private: - Gdiplus::Color gdiplus_color_; - Gdiplus::Pen *pen_; - Gdiplus::SolidBrush *brush_; - // The code below ensures that a connection to GDIplus is only made once, and that the - // matching connection shutdown is also done exactly once. - enum { - STATE_CLOSED = 0, // no connection, token is invalid - STATE_STARTUP, // attempt to start up, avoid recursions for whatever reason - STATE_OPEN, // connection was successful and the token is valid - STATE_SHUTDOWN // shutting down the gdi connection, avoid possible recursion - }; - static int gdiplus_state_; // reflect the state of the GDIplus driver connection - static ULONG_PTR gdiplus_token_; // the token that GDIplus gives to us -public: - Fl_GDIplus_Graphics_Driver(); - virtual ~Fl_GDIplus_Graphics_Driver(); - bool active; - static void shutdown(void); - void color(Fl_Color c) FL_OVERRIDE; - Fl_Color color() FL_OVERRIDE { return color_; } - void color(uchar r, uchar g, uchar b) FL_OVERRIDE; - void line(int x, int y, int x1, int y1) FL_OVERRIDE; - void line(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; - void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; - void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; - void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; - void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; - void line_style(int style, int width, char* dashes) FL_OVERRIDE; - void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; - void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; - void draw_circle(int x, int y, int d, Fl_Color c) FL_OVERRIDE; - void transformed_vertex(double xf, double yf) FL_OVERRIDE; - void vertex(double x,double y) FL_OVERRIDE; - void end_points() FL_OVERRIDE; - void end_line() FL_OVERRIDE; - void end_loop() FL_OVERRIDE; - void end_polygon() FL_OVERRIDE; - void end_complex_polygon() FL_OVERRIDE; - void circle(double x, double y, double r) FL_OVERRIDE; - void antialias(int state) FL_OVERRIDE; - int antialias() FL_OVERRIDE; -}; - -#endif // USE_GDIPLUS - -#endif // FL_GDI_GRAPHICS_DRIVER_H diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx deleted file mode 100644 index 97b3244d1..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx +++ /dev/null @@ -1,322 +0,0 @@ -// -// Rectangle drawing routines for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2022 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - - -#include <config.h> -#include "Fl_GDI_Graphics_Driver.H" -#include <FL/Fl.H> -#include <FL/platform.H> -#include <FL/fl_draw.H> -#include "../../Fl_Screen_Driver.H" -#include "Fl_Font.H" - -#if USE_GDIPLUS - -Fl_GDIplus_Graphics_Driver::Fl_GDIplus_Graphics_Driver() : Fl_GDI_Graphics_Driver() { - if (!fl_current_xmap) color(FL_BLACK); - pen_ = new Gdiplus::Pen(gdiplus_color_, 1); - pen_->SetLineJoin(Gdiplus::LineJoinRound); - pen_->SetStartCap(Gdiplus::LineCapFlat); - pen_->SetEndCap(Gdiplus::LineCapFlat); - brush_ = new Gdiplus::SolidBrush(gdiplus_color_); - active = true; -} - -Fl_GDIplus_Graphics_Driver::~Fl_GDIplus_Graphics_Driver() { - delete pen_; - delete brush_; -} - -void Fl_GDIplus_Graphics_Driver::antialias(int state) { - active = state; -} - -int Fl_GDIplus_Graphics_Driver::antialias() { - return active; -} - -void Fl_GDIplus_Graphics_Driver::draw_circle(int x, int y, int d, Fl_Color c) { - Fl_Graphics_Driver::draw_circle(x, y, d, c); -} - -int Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED; -ULONG_PTR Fl_GDIplus_Graphics_Driver::gdiplus_token_ = 0; - -void Fl_GDIplus_Graphics_Driver::shutdown() { - if (gdiplus_state_ == STATE_OPEN) { - gdiplus_state_ = STATE_SHUTDOWN; - Gdiplus::GdiplusShutdown(Fl_GDIplus_Graphics_Driver::gdiplus_token_); - gdiplus_token_ = 0; - gdiplus_state_ = STATE_CLOSED; - } else if (gdiplus_state_ == STATE_CLOSED) { -// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called, but driver is closed."); - } else if (gdiplus_state_ == STATE_SHUTDOWN) { -// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called recursively."); - } else if (gdiplus_state_ == STATE_STARTUP) { -// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called while driver is starting up."); - } -} -#endif - -// Code used to switch output to an off-screen window. See macros in -// win32.H which save the old state in local variables. - -typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION; -typedef BOOL (WINAPI* fl_alpha_blend_func) -(HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION); -static fl_alpha_blend_func fl_alpha_blend = NULL; -static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1}; - -/* Reference to the current device context - For back-compatibility only. The preferred procedure to get this reference is - Fl_Surface_Device::surface()->driver()->gc(). - */ -HDC fl_gc = 0; - - -HDC fl_win32_gc() { return fl_gc; } - - -Fl_GDI_Graphics_Driver::Fl_GDI_Graphics_Driver() { - mask_bitmap_ = NULL; - gc_ = NULL; - long_point = NULL; - depth = -1; - origins = NULL; - style_ = FL_SOLID; -} - -Fl_GDI_Graphics_Driver::~Fl_GDI_Graphics_Driver() { - if (long_point) free(long_point); - delete[] origins; -} - -void Fl_GDI_Graphics_Driver::global_gc() -{ - fl_gc = (HDC)gc(); -} - -/* - * This function checks if the version of Windows that we - * curently run on supports alpha blending for bitmap transfers - * and finds the required function if so. - */ -char Fl_GDI_Graphics_Driver::can_do_alpha_blending() { - static char been_here = 0; - static char can_do = 0; - // do this test only once - if (been_here) return can_do; - been_here = 1; - // load the library that implements alpha blending - HMODULE hMod = LoadLibrary("MSIMG32.DLL"); - // give up if that doesn't exist (Win95?) - if (!hMod) return 0; - // now find the blending function inside that dll - fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend"); - // give up if we can't find it (Win95) - if (!fl_alpha_blend) return 0; - // we have the call, but does our display support alpha blending? - // get the desktop's device context - HDC dc = GetDC(0L); - if (!dc) return 0; - // check the device capabilities flags. However GetDeviceCaps - // does not return anything useful, so we have to do it manually: - - HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1); - HDC new_gc = CreateCompatibleDC(dc); - int save = SaveDC(new_gc); - SelectObject(new_gc, bm); - /*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101); - BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc); - RestoreDC(new_gc, save); - DeleteDC(new_gc); - DeleteObject(bm); - ReleaseDC(0L, dc); - - if (alpha_ok) can_do = 1; - return can_do; -} - -HDC fl_makeDC(HBITMAP bitmap) { - HDC new_gc = CreateCompatibleDC((HDC)Fl_Graphics_Driver::default_driver().gc()); - SetTextAlign(new_gc, TA_BASELINE|TA_LEFT); - SetBkMode(new_gc, TRANSPARENT); -#if USE_COLORMAP - if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE); -#endif - SelectObject(new_gc, bitmap); - return new_gc; -} - -void Fl_GDI_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) { - x = int(x * scale()); y = int(y * scale()); w = int(w * scale()); h = int(h * scale()); - srcx = int(srcx * scale()); srcy = int(srcy * scale()); - if (srcx < 0) {w += srcx; x -= srcx; srcx = 0;} - if (srcy < 0) {h += srcy; y -= srcy; srcy = 0;} - int off_width, off_height; - Fl::screen_driver()->offscreen_size(bitmap, off_width, off_height); - if (srcx + w >= off_width) {w = off_width - srcx;} - if (srcy + h >= off_height) {h = off_height - srcy;} - if (w <= 0 || h <= 0) return; - HDC new_gc = CreateCompatibleDC(gc_); - int save = SaveDC(new_gc); - SelectObject(new_gc, (HBITMAP)bitmap); - BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); - RestoreDC(new_gc, save); - DeleteDC(new_gc); -} - -void Fl_GDI_Printer_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) { - Fl_Graphics_Driver::copy_offscreen(x, y, w, h, bitmap, srcx, srcy); -} - -BOOL Fl_GDI_Graphics_Driver::alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch) { - return fl_alpha_blend(gc_, x, y, w, h, src_gc, srcx, srcy, srcw, srch, blendfunc); -} - -#if ! defined(FL_DOXYGEN) -void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { - HDC new_gc = CreateCompatibleDC(gc_); - int save = SaveDC(new_gc); - SelectObject(new_gc, bitmap); - BOOL alpha_ok = 0; - // first try to alpha blend - if ( fl_can_do_alpha_blending() ) { - alpha_ok = alpha_blend_(x, y, w, h, new_gc, srcx, srcy, w, h); - } - // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1 - if (!alpha_ok) { - BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); - } - RestoreDC(new_gc, save); - DeleteDC(new_gc); -} - -void Fl_GDI_Graphics_Driver::translate_all(int x, int y) { - const int stack_height = 10; - if (depth == -1) { - origins = new POINT[stack_height]; - depth = 0; - } - if (depth >= stack_height) { - Fl::warning("Fl_Copy/Image_Surface: translate stack overflow!"); - depth = stack_height - 1; - } - GetWindowOrgEx((HDC)gc(), origins+depth); - SetWindowOrgEx((HDC)gc(), int(origins[depth].x - x*scale()), int(origins[depth].y - y*scale()), NULL); - depth++; -} - -void Fl_GDI_Graphics_Driver::untranslate_all() { - if (depth > 0) depth--; - SetWindowOrgEx((HDC)gc(), origins[depth].x, origins[depth].y, NULL); -} -#endif - -void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) { - HRGN R = (HRGN)XRectangleRegion(X, Y, W, H); - CombineRgn((HRGN)r, (HRGN)r, R, RGN_OR); - XDestroyRegion(R); -} - -void Fl_GDI_Graphics_Driver::transformed_vertex0(float x, float y) { - if (!n || x != long_point[n-1].x || y != long_point[n-1].y) { - if (n >= p_size) { - p_size = long_point ? 2*p_size : 16; - long_point = (POINT*)realloc((void*)long_point, p_size*sizeof(*long_point)); - } - long_point[n].x = LONG(x); - long_point[n].y = LONG(y); - n++; - } -} - -void Fl_GDI_Graphics_Driver::fixloop() { // remove equal points from closed path - while (n>2 && long_point[n-1].x == long_point[0].x && long_point[n-1].y == long_point[0].y) n--; -} - -Fl_Region Fl_GDI_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { - if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) return CreateRectRgn(x,y,x+w,y+h); - // because rotation may apply, the rectangle becomes a polygon in device coords - POINT pt[4] = { {x, y}, {x + w, y}, {x + w, y + h}, {x, y + h} }; - LPtoDP((HDC)fl_graphics_driver->gc(), pt, 4); - return CreatePolygonRgn(pt, 4, ALTERNATE); -} - -void Fl_GDI_Graphics_Driver::XDestroyRegion(Fl_Region r) { - DeleteObject((HRGN)r); -} - - -void Fl_GDI_Graphics_Driver::scale(float f) { - if (f != scale()) { - size_ = 0; - Fl_Graphics_Driver::scale(f); - color(FL_BLACK); - line_style(FL_SOLID); // scale also default line width - } -} - - -/* Rescale region r with factor f and returns the scaled region. - Region r is returned unchanged if r is null or f is 1. - */ -HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr) { - if (r && f != 1) { - DWORD size = GetRegionData(r, 0, NULL); - RGNDATA *pdata = (RGNDATA*)malloc(size); - GetRegionData(r, size, pdata); - POINT pt = {0, 0}; - if (dr && dr->depth >= 1) { // account for translation - GetWindowOrgEx((HDC)dr->gc(), &pt); - pt.x = int(pt.x * (f - 1)); - pt.y = int(pt.y * (f - 1)); - } - RECT *rects = (RECT*)&(pdata->Buffer); - for (DWORD i = 0; i < pdata->rdh.nCount; i++) { - int x = Fl_Scalable_Graphics_Driver::floor(rects[i].left, f) + pt.x; - int y = Fl_Scalable_Graphics_Driver::floor(rects[i].top, f) + pt.y; - RECT R2; - R2.left = x; - R2.top = y; - R2.right = Fl_Scalable_Graphics_Driver::floor(rects[i].right, f) + pt.x - x + R2.left; - R2.bottom = Fl_Scalable_Graphics_Driver::floor(rects[i].bottom, f) + pt.y - y + R2.top; - rects[i] = R2; - } - r = ExtCreateRegion(NULL, size, pdata); - free(pdata); - } - return r; -} - - -Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) { - HRGN r = (HRGN)rstack[rstackptr]; - HRGN r2 = scale_region(r, f, this); - return (r == r2 ? NULL : (rstack[rstackptr] = r2, r)); -} - -void Fl_GDI_Graphics_Driver::set_current_() { - restore_clip(); -} - -void Fl_GDI_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) -{ - float s = scale(); - width = (s == int(s) ? width * int(s) : floor(width+1)); - height = (s == int(s) ? height * int(s) : floor(height+1)); - cache_size_finalize(img, width, height); -} diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx deleted file mode 100644 index 0c1e90064..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx +++ /dev/null @@ -1,89 +0,0 @@ -// -// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -/** - \file Fl_GDI_Graphics_Driver_arci.cxx - \brief Utility functions for drawing circles using integers -*/ - -// "integer" circle drawing functions. These draw the limited -// circle types provided by X and NT graphics. The advantage of -// these is that small ones draw quite nicely (probably due to stored -// hand-drawn bitmaps of small circles!) and may be implemented by -// hardware and thus are fast. - -#include "Fl_GDI_Graphics_Driver.H" - -#include <FL/math.h> -#include <FL/platform.H> - -void Fl_GDI_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) { - if (w <= 0 || h <= 0) return; - w++; h++; - int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) ); - int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) ); - int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) ); - int yb = int( y+h/2-int(h*sin(a2/180.0*M_PI)) ); - if (fabs(a1 - a2) < 90) { - if (xa == xb && ya == yb) SetPixel(gc_, xa, ya, fl_RGB()); - else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); - } else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); -} - -void Fl_GDI_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) { - if (w <= 0 || h <= 0) return; - if (a1 == a2) return; - x++; y++; w--; h--; - if (scale() >= 3) {x++; y++; w-=2; h-=2;} - int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) ); - int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) ); - int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) ); - int yb = int( y+h/2-int(h*sin(a2/180.0*M_PI)) ); - SelectObject(gc_, fl_brush()); - if (fabs(a1 - a2) < 90) { - if (xa == xb && ya == yb) { - MoveToEx(gc_, int(x+w/2), int(y+h/2), 0L); - LineTo(gc_, xa, ya); - SetPixel(gc_, xa, ya, fl_RGB()); - } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); - } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); -} - -#if USE_GDIPLUS - -void Fl_GDIplus_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) { - if (w <= 0 || h <= 0) return; - if (!active) return Fl_GDI_Graphics_Driver::arc_unscaled(x, y, w, h, a1, a2); - Gdiplus::Graphics graphics_(gc_); - pen_->SetColor(gdiplus_color_); - Gdiplus::REAL oldw = pen_->GetWidth(); - Gdiplus::REAL new_w = (line_width_ <= scale() ? 1 : line_width_) * scale(); - pen_->SetWidth(new_w); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.DrawArc(pen_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2)); - pen_->SetWidth(oldw); -} - -void Fl_GDIplus_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) { - if (w <= 0 || h <= 0) return; - if (!active) return Fl_GDI_Graphics_Driver::pie_unscaled(x, y, w, h, a1, a2); - Gdiplus::Graphics graphics_(gc_); - brush_->SetColor(gdiplus_color_); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.FillPie(brush_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2)); -} - -#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx deleted file mode 100644 index c05a255d0..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx +++ /dev/null @@ -1,259 +0,0 @@ -// -// MSWidnows' GDI color functions for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.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/platform.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? -// FIXME: ... but for now we still have it ... -extern unsigned fl_cmap[256]; // defined in fl_color.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((HDC)fl_graphics_driver->gc(), tmppen); -} - -void fl_restore_pen(void) { - if (savepen) SelectObject((HDC)fl_graphics_driver->gc(), savepen); - DeleteObject(tmppen); - tmppen = 0; - savepen = 0; -} - -static void clear_xmap(Fl_XMap& xmap) { - if (xmap.pen) { - HDC gc = (HDC)fl_graphics_driver->gc(); - HGDIOBJ tmppen = GetStockObject(BLACK_PEN); - HGDIOBJ oldpen = SelectObject(gc, tmppen); // Push out the current pen of the gc - if(oldpen != xmap.pen) SelectObject(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, int lw) { - xmap.rgb = c; - if (xmap.pen) { - HDC gc = (HDC)fl_graphics_driver->gc(); - HGDIOBJ oldpen = SelectObject(gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one - if (oldpen != xmap.pen)SelectObject(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 - LOGBRUSH penbrush = {BS_SOLID, xmap.rgb, 0}; - xmap.pen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, lw, &penbrush, 0, 0); - xmap.pwidth = lw; - xmap.brush = -1; -} - -void Fl_GDI_Graphics_Driver::color(Fl_Color i) { - if (i & 0xffffff00) { - unsigned rgb = (unsigned)i; - color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); - } else { - Fl_Graphics_Driver::color(i); - Fl_XMap &xmap = fl_xmap[i]; - int tw = line_width_ ? line_width_ : int(scale()); if (!tw) tw = 1; - if (!xmap.pen || xmap.pwidth != tw) { -#if USE_COLORMAP - if (fl_palette) { - set_xmap(xmap, PALETTEINDEX(i), tw); - } else { -#endif - unsigned c = fl_cmap[i]; - set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)), tw); -#if USE_COLORMAP - } -#endif - } - fl_current_xmap = ⟼ - SelectObject(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) ); - int tw = line_width_ ? line_width_ : int(scale()); if (!tw) tw = 1; - if (!xmap.pen || c != xmap.rgb || tw != xmap.pwidth) { - clear_xmap(xmap); - set_xmap(xmap, c, tw); - } - fl_current_xmap = ⟼ - SelectObject(gc_, (HGDIOBJ)(xmap.pen)); -} - -HBRUSH fl_brush() { - return fl_brush_action(0); -} - -HBRUSH fl_brush_action(int action) { - Fl_XMap *xmap = fl_current_xmap; - HDC gc = (HDC)fl_graphics_driver->gc(); - // 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(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(gc,tmpbrush); // load in into current context - if (oldbrush != brushes[i].brush) SelectObject(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_GDI_Graphics_Driver::free_color(Fl_Color i, int overlay) { - if (overlay) return; // do something about GL overlay? - clear_xmap(fl_xmap[i]); -} - -void Fl_GDI_Graphics_Driver::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; - HDC gc = (HDC)fl_graphics_driver->gc(); - if (!beenhere) { - beenhere = 1; - - int nColors = GetDeviceCaps(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(gc, fl_palette, FALSE); - RealizePalette(gc); - } - return fl_palette; -} - -#endif - -#if USE_GDIPLUS -void Fl_GDIplus_Graphics_Driver::color(uchar r, uchar g, uchar b) { - Fl_GDI_Graphics_Driver::color(r, g, b); - gdiplus_color_.SetFromCOLORREF(fl_RGB()); -} - -void Fl_GDIplus_Graphics_Driver::color(Fl_Color i) { - Fl_GDI_Graphics_Driver::color(i); - gdiplus_color_.SetFromCOLORREF(fl_RGB()); -} -#endif // USE_GDIPLUS diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx deleted file mode 100644 index 49111f10e..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx +++ /dev/null @@ -1,678 +0,0 @@ -// -// Windows font utilities for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2026 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -#include <config.h> - -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -/* We require Windows 2000 features such as GetGlyphIndices */ -#if !defined(WINVER) || (WINVER < 0x0500) -# ifdef WINVER -# undef WINVER -# endif -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# ifdef _WIN32_WINNT -# undef _WIN32_WINNT -# endif -# define _WIN32_WINNT 0x0500 -#endif - -// Select fonts from the FLTK font table. -#include "Fl_GDI_Graphics_Driver.H" -#include "../../flstring.h" -#include <FL/Fl.H> -#include <FL/fl_draw.H> -#include <FL/platform.H> -#include "Fl_Font.H" - -#include <stdio.h> -#include <stdlib.h> -#include <FL/fl_string_functions.h> - -// 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_GDI_Graphics_Driver::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; - -// helper function for `enumcbw()` to avoid code repetition -// input: -// ft: font "type", i.e. ' ', 'B', 'I', or 'P' -// fn: font name whose first byte is overwritten and then stored - -static void set_font_name(const char ft, char *fn) { - fn[0] = ft; - Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(fn)); -} - -// Callback for EnumFontFamiliesW(): -// return 1 to continue, 0 to stop enumeration - -static int CALLBACK -enumcbw(CONST LOGFONTW *lpelf, - CONST TEXTMETRICW * /* lpntm */, - DWORD /* FontType */, - LPARAM p) { - if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1; - char *fn = nullptr; // FLTK font name - unsigned lw = (unsigned)wcslen(lpelf->lfFaceName); - unsigned dstlen = fl_utf8fromwc(fn, 0, (wchar_t*)lpelf->lfFaceName, lw); // measure the string - fn = (char*)malloc((size_t)dstlen + 2); // "?" + name + NUL - if (!fn) return 1; - fn[0] = ' '; - dstlen = fl_utf8fromwc(fn+1, dstlen+1, (wchar_t*)lpelf->lfFaceName, lw); // convert the string - fn[dstlen + 1] = 0; - // skip if it is one of our built-in fonts - for (int i = 0; i < FL_FREE_FONT; i++) { - if (!strcmp(Fl::get_font_name((Fl_Font)i), fn+1)) { - free(fn); - return 1; - } - } - set_font_name(' ', fn); - if (lpelf->lfWeight <= 400) - set_font_name('B', fn); - set_font_name('I', fn); - if (lpelf->lfWeight <= 400) - set_font_name('P', fn); - free(fn); - return 1; -} /* enumcbw */ - -Fl_Font Fl_GDI_Graphics_Driver::set_fonts(const char* xstarname) { - HDC gc = (HDC)fl_graphics_driver->gc(); - if (fl_free_font == FL_FREE_FONT) {// if not already been called - if (!gc) gc = fl_GetDC(0); - - EnumFontFamiliesW(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_GDI_Graphics_Driver::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 - - HDC gc = (HDC)fl_graphics_driver->gc(); - if (!gc) gc = fl_GetDC(0); - cyPerInch = GetDeviceCaps(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, (wchar_t*)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(gc, (WCHAR*)b, (FONTENUMPROCW)EnumSizeCbW, 0); - free(b); - - sizep = sizes; - return nbSize; -} - -const char *Fl_GDI_Graphics_Driver::font_name(int num) { - return fl_fonts[num].name; -} - -void Fl_GDI_Graphics_Driver::font_name(int num, const char *name) { - Fl_Fontdesc *s = fl_fonts + num; - if (s->name) { - if (!strcmp(s->name, name)) {s->name = name; return;} - for (Fl_Font_Descriptor* f = s->first; f;) { - Fl_Font_Descriptor* n = f->next; delete f; f = n; - } - s->first = 0; - } - s->name = name; - s->fontname[0] = 0; - s->first = 0; -} - - -static int fl_angle_ = 0; -// Unicode string buffer -static unsigned short *wstr = NULL; -static int wstr_len = 0; - -#ifndef FL_DOXYGEN -Fl_GDI_Font_Descriptor::Fl_GDI_Font_Descriptor(const char* name, Fl_Fontsize fsize) : Fl_Font_Descriptor(name,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--; - } - int wn = fl_utf8toUtf16(name, (unsigned int)strlen(name), wstr, wstr_len); - if (wn >= wstr_len) { - wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1)); - wstr_len = wn + 1; - wn = fl_utf8toUtf16(name, (unsigned int)strlen(name), wstr, wstr_len); - } - - fid = CreateFontW( - -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 - (LPCWSTR)wstr // pointer to typeface name string - ); - angle = fl_angle_; - HDC gc = (HDC)fl_graphics_driver->gc(); - if (!gc) gc = fl_GetDC(0); - SelectObject(gc, fid); - GetTextMetrics(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 - for (i = 0; i < 64; i++) glok[i] = 0; -#endif - size = fsize; -} - -Fl_GDI_Font_Descriptor::~Fl_GDI_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? -#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[] = { - {" Microsoft Sans Serif"}, - {"BMicrosoft Sans Serif"}, - {"IMicrosoft Sans Serif"}, - {"PMicrosoft Sans Serif"}, -{" 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_GDI_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_GDI_Font_Descriptor* f; - for (f = (Fl_GDI_Font_Descriptor*)s->first; f; f = (Fl_GDI_Font_Descriptor*)f->next) - if (f->size == size && f->angle == angle) return f; - f = new Fl_GDI_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 == ((Fl_GDI_Graphics_Driver*)driver)->size_unscaled() && 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_unscaled(Fl_Font fnum, Fl_Fontsize size) { - fl_font(this, fnum, size, 0); -} - -int Fl_GDI_Graphics_Driver::height_unscaled() { - Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor(); - if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent); - else return -1; -} - -int Fl_GDI_Graphics_Driver::descent_unscaled() { - Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor(); - if (fl_fontsize) return fl_fontsize->metr.tmDescent; - else return -1; -} - -Fl_Fontsize Fl_GDI_Graphics_Driver::size_unscaled() { - if (font_descriptor()) return size_; - return -1; -} - -double Fl_GDI_Graphics_Driver::width_unscaled(const char* c, int n) { - if (n == 0) return 0; - int len1 = fl_utf8len1(*c); - if (n > len1 && len1 > 0) { // a text with several codepoints: compute its typographical width - int 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); - } - HDC gc2 = gc_; - HWND hWnd; - if (!gc2) { - hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; - gc2 = GetDC(hWnd); - } - SelectObject(gc2, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid); - SIZE s; - GetTextExtentPoint32W(gc2, (WCHAR*)wstr, wn, &s); - if (gc2 && gc2 != gc_) ReleaseDC(hWnd, gc2); - return (double)s.cx; - } - 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_unscaled(ucs); - } - } - return w; -} - -double Fl_GDI_Graphics_Driver::width_unscaled(unsigned int c) { - Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)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 (!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(gc_, fl_fontsize->fid); - // measure the glyph width - GetTextExtentPoint32W(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 gc2 = gc_; - HWND hWnd = 0; - if (!gc2) { // 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; - gc2 = GetDC(hWnd); - } - if (!gc2) Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!"); - SelectObject(gc2, fl_fontsize->fid); - ii += c &0x03FF; - GetTextExtentPoint32W(gc2, (WCHAR*)&ii, 1, &s); - fl_fontsize->width[r][c&0x03FF] = s.cx; - if (gc2 && gc2 != gc_) ReleaseDC(hWnd, gc2); - 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, HDC gc) -// converts text extents from device coords to logical coords -{ - POINT pt[3] = { {0, 0}, {dx, dy}, {dx+w, dy+h} }; - DPtoLP(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,gc) \ - if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { \ - on_printer_extents_update(x,y,w,h,gc); \ - } - -// Function to determine the extent of the "inked" area of the glyphs in a string -void Fl_GDI_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) { - - Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)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 gc2 = 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 (!gc2) { // 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; - gc2 = GetDC(hWnd); - } - if (!gc2) 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(gc2, 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(gc2, (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 occurred 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 (gc2, 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, gc_); - return; // normal exit - -exit_error: - // some error here - just return fl_measure values - w = (int)width(c, n); - h = height_unscaled(); - dx = 0; - dy = descent_unscaled() - h; - EXTENTS_UPDATE(dx, dy, w, h, gc_); - return; -} // fl_text_extents - -void Fl_GDI_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y) { - COLORREF oldColor = SetTextColor(gc_, fl_RGB()); - // avoid crash if no font has been set yet - if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); - SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)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(gc_, x, y, (WCHAR*)wstr, wn); - SetTextColor(gc_, oldColor); // restore initial state -} - -void Fl_GDI_Graphics_Driver::draw_unscaled(int angle, const char* str, int n, int x, int y) { - fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), angle); - int wn = 0; // count of UTF16 cells to render full string - COLORREF oldColor = SetTextColor(gc_, fl_RGB()); - SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)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(gc_, x, y, (WCHAR*)wstr, wn); - SetTextColor(gc_, oldColor); - fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), 0); -} - -void Fl_GDI_Graphics_Driver::rtl_draw_unscaled(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(gc_, fl_RGB()); - SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)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(gc_, x, y, (WCHAR*)wstr + i, 1); - if (fl_nonspacing(wstr[i])) { - x += lx; - } - i++; - } -#else - UINT old_align = SetTextAlign(gc_, TA_RIGHT | TA_RTLREADING); - TextOutW(gc_, x, y - height_unscaled() + descent_unscaled(), (WCHAR*)wstr, wn); - SetTextAlign(gc_, old_align); -#endif - SetTextColor(gc_, oldColor); -} -#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx deleted file mode 100644 index 3a8e70689..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx +++ /dev/null @@ -1,826 +0,0 @@ -// -// Windows image drawing code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2024 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -// I hope a simple and portable method of drawing color and monochrome -// images. To keep this simple, only a single storage type is -// supported: 8 bit unsigned data, byte order RGB, and pixels are -// stored packed into rows with the origin at the top-left. It is -// possible to alter the size of pixels with the "delta" argument, to -// add alpha or other information per pixel. It is also possible to -// change the origin and direction of the image data by messing with -// the "delta" and "linedelta", making them negative, though this may -// defeat some of the shortcuts in translating the image for X. - -// Unbelievably (since it conflicts with how most PC software works) -// Micro$oft picked a bottom-up and BGR storage format for their -// DIB images. I'm pretty certain there is a way around this, but -// I can't find any other than the brute-force method of drawing -// each line as a separate image. This may also need to be done -// if the delta is any amount other than 1, 3, or 4. - -//////////////////////////////////////////////////////////////// - -#include <config.h> -#include "Fl_GDI_Graphics_Driver.H" -#include "../WinAPI/Fl_WinAPI_System_Driver.H" -#include <FL/Fl.H> -#include <FL/fl_draw.H> -#include <FL/platform.H> -#include <FL/Fl_Image_Surface.H> - -#define MAXBUFFER 0x40000 // 256k - -void fl_release_dc(HWND, HDC); // from Fl_win32.cxx - -#if USE_COLORMAP - -// error-diffusion dither into the FLTK colormap -static void dither(uchar* to, const uchar* from, int w, int delta) { - static int ri, gi, bi, dir; - int r=ri, g=gi, b=bi; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - to = to+(w-1); - d = -delta; - td = -1; - } else { - dir = 1; - d = delta; - td = 1; - } - for (; w--; from += d, to += td) { - r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; - int rr = r*FL_NUM_RED/256; - r -= rr*255/(FL_NUM_RED-1); - g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; - int gg = g*FL_NUM_GREEN/256; - g -= gg*255/(FL_NUM_GREEN-1); - b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; - int bb = b*FL_NUM_BLUE/256; - b -= bb*255/(FL_NUM_BLUE-1); - *to = uchar(FL_COLOR_CUBE+(bb*FL_NUM_RED+rr)*FL_NUM_GREEN+gg); - } - ri = r; gi = g; bi = b; -} - -// error-diffusion dither into the FLTK colormap -static void monodither(uchar* to, const uchar* from, int w, int delta) { - static int ri,dir; - int r=ri; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - to = to+(w-1); - d = -delta; - td = -1; - } else { - dir = 1; - d = delta; - td = 1; - } - for (; w--; from += d, to += td) { - r += *from; if (r < 0) r = 0; else if (r>255) r = 255; - int rr = r*FL_NUM_GRAY/256; - r -= rr*255/(FL_NUM_GRAY-1); - *to = uchar(FL_GRAY_RAMP+rr); - } - ri = r; -} - -#endif // USE_COLORMAP - -static int fl_abs(int v) { return v<0 ? -v : v; } - -static void innards(const uchar *buf, int X, int Y, int W, int H, - int delta, int linedelta, int depth, - Fl_Draw_Image_Cb cb, void* userdata, HDC gc) -{ - char indexed = 0; - -#if USE_COLORMAP - indexed = (fl_palette != 0); -#endif - - if (depth==0) depth = 3; - if (indexed || !fl_can_do_alpha_blending()) - depth = (depth-1)|1; - - if (!linedelta) linedelta = W*fl_abs(delta); - - int x = 0, y = 0, w = 0, h = 0; - fl_clip_box(X, Y, W, H, x, y, w, h); - if (w<=0 || h<=0) return; - if (buf) buf += (x-X)*delta + (y-Y)*linedelta; - - // bmibuffer: BITMAPINFOHEADER + 256 colors (RGBQUAD) + 1 (rounding effects ?) - static U32 bmibuffer[sizeof(BITMAPINFOHEADER)/4 + 257]; - BITMAPINFO *bmi = (BITMAPINFO*)bmibuffer; - if (!bmi->bmiHeader.biSize) { - bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi->bmiHeader.biPlanes = 1; - bmi->bmiHeader.biCompression = BI_RGB; - bmi->bmiHeader.biXPelsPerMeter = 0; - bmi->bmiHeader.biYPelsPerMeter = 0; - bmi->bmiHeader.biClrUsed = 0; - bmi->bmiHeader.biClrImportant = 0; - } -#if USE_COLORMAP - if (indexed) { - for (short i=0; i<256; i++) { - *((short*)(bmi->bmiColors)+i) = i; - } - } else -#endif - if (depth<3) { - RGBQUAD *bmi_colors = &(bmi->bmiColors[0]); // use pointer to suppress warning (STR #3199) - for (int i=0; i<256; i++) { - bmi_colors[i].rgbBlue = (uchar)i; // = bmi->bmiColors[i] - bmi_colors[i].rgbGreen = (uchar)i; - bmi_colors[i].rgbRed = (uchar)i; - bmi_colors[i].rgbReserved = (uchar)0; // must be zero - } - } - bmi->bmiHeader.biWidth = w; -#if USE_COLORMAP - bmi->bmiHeader.biBitCount = indexed ? 8 : depth*8; - int pixelsize = indexed ? 1 : depth; -#else - bmi->bmiHeader.biBitCount = depth*8; - int pixelsize = depth; -#endif - if (depth==2) { // special case: gray with alpha - bmi->bmiHeader.biBitCount = 32; - pixelsize = 4; - } - int linesize = (pixelsize*w+3)&~3; - - static U32* buffer; - static long buffer_size; - int blocking = h; - { - int size = linesize * h; - // when printing, don't limit buffer size not to get a crash in StretchDIBits - if (size > MAXBUFFER && !fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) { - size = MAXBUFFER; - blocking = MAXBUFFER / linesize; - } - if (size > buffer_size) { - delete[] buffer; - buffer_size = size; - buffer = new U32[(size + 3) / 4]; - } - } - bmi->bmiHeader.biHeight = blocking; - static U32* line_buffer; - if (!buf) { - int size = W*delta; - static int line_buf_size; - if (size > line_buf_size) { - delete[] line_buffer; - line_buf_size = size; - line_buffer = new U32[(size+3)/4]; - } - } - for (int j=0; j<h; ) { - int k; - for (k = 0; j<h && k<blocking; k++, j++) { - const uchar* from; - if (!buf) { // run the converter: - cb(userdata, x-X, y-Y+j, w, (uchar*)line_buffer); - from = (uchar*)line_buffer; - } else { - from = buf; - buf += linedelta; - } - uchar *to = (uchar*)buffer+(blocking-k-1)*linesize; -#if USE_COLORMAP - if (indexed) { - if (depth<3) - monodither(to, from, w, delta); - else - dither(to, from, w, delta); - } else -#endif - { - int i; - switch (depth) { - case 1: - for (i=w; i--; from += delta) *to++ = *from; - break; - case 2: - for (i=w; i--; from += delta, to += 4) { - uchar a = from[1]; - uchar gray = (from[0]*a)>>8; - to[0] = gray; - to[1] = gray; - to[2] = gray; - to[3] = a; - } - break; - case 3: - for (i=w; i--; from += delta, to += 3) { - uchar r = from[0]; - to[0] = from[2]; - to[1] = from[1]; - to[2] = r; - } - break; - case 4: - for (i=w; i--; from += delta, to += 4) { - uchar a = from[3]; - uchar r = from[0]; - to[0] = (from[2]*a)>>8; - to[1] = (from[1]*a)>>8; - to[2] = (r*a)>>8; - to[3] = from[3]; - } - break; - } - } - } // for (k = 0; j<h && k<blocking ...) - - if (fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) { - // if print context, device and logical units are not equal, so SetDIBitsToDevice - // does not do the expected job, whereas StretchDIBits does it. - StretchDIBits(gc, x, y+j-k, w, k, 0, 0, w, k, - (LPSTR)((uchar*)buffer+(blocking-k)*linesize), - bmi, -#if USE_COLORMAP - indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS -#else - DIB_RGB_COLORS -#endif - , SRCCOPY ); - delete[] buffer; - buffer = NULL; - buffer_size = 0; - } - else { - SetDIBitsToDevice(gc, x, y+j-k, w, k, 0, 0, 0, k, - (LPSTR)((uchar*)buffer+(blocking-k)*linesize), - bmi, -#if USE_COLORMAP - indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS -#else - DIB_RGB_COLORS -#endif - ); - } - } // for (int j=0; j<h; ) -} - -void Fl_GDI_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){ - if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { - d ^= FL_IMAGE_WITH_ALPHA; - innards(buf,x,y,w,h,d,l,fl_abs(d),0,0, gc_); - } else { - innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0, gc_); - } -} - -void Fl_GDI_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, - int x, int y, int w, int h,int d) { - if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { - d ^= FL_IMAGE_WITH_ALPHA; - innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data, gc_); - } else { - innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data, gc_); - } -} - -void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){ - if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { - d ^= FL_IMAGE_WITH_ALPHA; - innards(buf,x,y,w,h,d,l,1,0,0, gc_); - } else { - innards(buf,x,y,w,h,d,l,1,0,0, gc_); - } -} - -void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, - int x, int y, int w, int h,int d) { - if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { - d ^= FL_IMAGE_WITH_ALPHA; - innards(0,x,y,w,h,d,0,1,cb,data, gc_); - } else { - innards(0,x,y,w,h,d,0,1,cb,data, gc_); - } -} - -#if USE_COLORMAP -void Fl_GDI_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { - // use the error diffusion dithering code to produce a much nicer block: - if (fl_palette) { - uchar c[3]; - c[0] = r; c[1] = g; c[2] = b; - innards(c, floor(x), floor(y), floor(x + w) - floor(x), floor(y + h) - floor(y), - 0,0,0,0,0, (HDC)gc()); - return; - } - Fl_Graphics_Driver::colored_rectf(x, y, w, h, r, g, b); -} -#endif - -// Create an N-bit bitmap for masking... -HBITMAP Fl_GDI_Graphics_Driver::create_bitmask(int w, int h, const uchar *data) { - // this won't work when the user changes display mode during run or - // has two screens with different depths - HBITMAP bm; - static uchar hiNibble[16] = - { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 }; - static uchar loNibble[16] = - { 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, - 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f }; - HDC current_gc = (HDC)Fl_Surface_Device::surface()->driver()->gc(); - int np = GetDeviceCaps(current_gc, PLANES); //: was always one on sample machines - int bpp = GetDeviceCaps(current_gc, BITSPIXEL);//: 1,4,8,16,24,32 and more odd stuff? - int Bpr = (bpp*w+7)/8; //: bytes per row - int pad = Bpr&1, w1 = (w+7)/8, shr = ((w-1)&7)+1; - if (bpp==4) shr = (shr+1)/2; - uchar *newarray = new uchar[(Bpr+pad)*h]; - uchar *dst = newarray; - const uchar *src = data; - - for (int i=0; i<h; i++) { - // This is slooow, but we do it only once per pixmap - for (int j=w1; j>0; j--) { - uchar b = *src++; - if (bpp==1) { - *dst++ = (uchar)( hiNibble[b&15] ) | ( loNibble[(b>>4)&15] ); - } else if (bpp==4) { - for (int k=(j==1)?shr:4; k>0; k--) { - *dst++ = (uchar)("\377\360\017\000"[b&3]); - b = b >> 2; - } - } else { - for (int k=(j==1)?shr:8; k>0; k--) { - if (b&1) { - *dst++=0; - if (bpp>8) *dst++=0; - if (bpp>16) *dst++=0; - if (bpp>24) *dst++=0; - } else { - *dst++=0xff; - if (bpp>8) *dst++=0xff; - if (bpp>16) *dst++=0xff; - if (bpp>24) *dst++=0xff; - } - - b = b >> 1; - } - } - } - - dst += pad; - } - - bm = CreateBitmap(w, h, np, bpp, newarray); - delete[] newarray; - - return bm; -} - -void Fl_GDI_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) { - DeleteObject((HGDIOBJ)bm); -} - -void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { - X = this->floor(X); - Y = this->floor(Y); - cache_size(bm, W, H); - cx = this->floor(cx); cy = this->floor(cy); - - HDC tempdc = CreateCompatibleDC(gc_); - int save = SaveDC(tempdc); - SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm)); - SelectObject(gc_, fl_brush()); - // secret bitblt code found in old Windows reference manual: - BitBlt(gc_, X, Y, W, H, tempdc, cx, cy, 0xE20746L); - RestoreDC(tempdc, save); - DeleteDC(tempdc); -} - -Fl_GDI_Printer_Graphics_Driver::transparent_f_type Fl_GDI_Printer_Graphics_Driver::TransparentBlt() { - HMODULE hMod; - static transparent_f_type fpter = ( (hMod = LoadLibrary("MSIMG32.DLL")) ? - (transparent_f_type)GetProcAddress(hMod, "TransparentBlt") : NULL - ); - return fpter; -} - -void Fl_GDI_Printer_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { - return; - } - transparent_f_type fl_TransparentBlt = TransparentBlt(); - if (!fl_TransparentBlt) { - Fl_Graphics_Driver::draw_bitmap(bm, X, Y, W, H, cx, cy); - return; - } - bool recache = false; - if (*id(bm)) { - int *pw, *ph; - cache_w_h(bm, pw, ph); - recache = (*pw != bm->data_w() || *ph != bm->data_h()); - } - if (recache || !*id(bm)) { - bm->uncache(); - cache(bm); - } - HDC tempdc; - int save; - // algorithm for bitmap output to Fl_GDI_Printer - Fl_Color save_c = fl_color(); // save bitmap's desired color - uchar r, g, b; - Fl::get_color(save_c, r, g, b); - r = 255-r; - g = 255-g; - b = 255-b; - Fl_Color background = fl_rgb_color(r, g, b); // a color very different from the bitmap's - Fl_Image_Surface *img_surf = new Fl_Image_Surface(bm->data_w(), bm->data_h()); - Fl_Surface_Device::push_current(img_surf); - fl_color(background); - fl_rectf(0,0, bm->data_w(), bm->data_h()); // use this color as offscreen background - fl_color(save_c); // back to bitmap's color - HDC off_gc = (HDC)fl_graphics_driver->gc(); - tempdc = CreateCompatibleDC(off_gc); - save = SaveDC(tempdc); - SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm)); - SelectObject(off_gc, fl_brush()); // use bitmap's desired color - BitBlt(off_gc, 0, 0, bm->data_w(), bm->data_h(), tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen - Fl_Surface_Device::pop_current(); - SelectObject(tempdc, (HGDIOBJ)img_surf->offscreen()); // use offscreen data - // draw it to printer context with background color as transparent - float scaleW = bm->data_w()/float(bm->w()); - float scaleH = bm->data_h()/float(bm->h()); - fl_TransparentBlt(gc_, X, Y, W, H, tempdc, - int(cx * scaleW), int(cy * scaleH), int(W * scaleW), int(H * scaleH), RGB(r, g, b) ); - delete img_surf; - RestoreDC(tempdc, save); - DeleteDC(tempdc); - if (recache) bm->uncache(); -} - - -// Create a 1-bit mask used for alpha blending -HBITMAP Fl_GDI_Graphics_Driver::create_alphamask(int w, int h, int d, int ld, const uchar *array) { - HBITMAP bm; - int bmw = (w + 7) / 8; - uchar *bitmap = new uchar[bmw * h]; - uchar *bitptr, bit; - const uchar *dataptr; - int x, y; - static uchar dither[16][16] = { // Simple 16x16 Floyd dither - { 0, 128, 32, 160, 8, 136, 40, 168, - 2, 130, 34, 162, 10, 138, 42, 170 }, - { 192, 64, 224, 96, 200, 72, 232, 104, - 194, 66, 226, 98, 202, 74, 234, 106 }, - { 48, 176, 16, 144, 56, 184, 24, 152, - 50, 178, 18, 146, 58, 186, 26, 154 }, - { 240, 112, 208, 80, 248, 120, 216, 88, - 242, 114, 210, 82, 250, 122, 218, 90 }, - { 12, 140, 44, 172, 4, 132, 36, 164, - 14, 142, 46, 174, 6, 134, 38, 166 }, - { 204, 76, 236, 108, 196, 68, 228, 100, - 206, 78, 238, 110, 198, 70, 230, 102 }, - { 60, 188, 28, 156, 52, 180, 20, 148, - 62, 190, 30, 158, 54, 182, 22, 150 }, - { 252, 124, 220, 92, 244, 116, 212, 84, - 254, 126, 222, 94, 246, 118, 214, 86 }, - { 3, 131, 35, 163, 11, 139, 43, 171, - 1, 129, 33, 161, 9, 137, 41, 169 }, - { 195, 67, 227, 99, 203, 75, 235, 107, - 193, 65, 225, 97, 201, 73, 233, 105 }, - { 51, 179, 19, 147, 59, 187, 27, 155, - 49, 177, 17, 145, 57, 185, 25, 153 }, - { 243, 115, 211, 83, 251, 123, 219, 91, - 241, 113, 209, 81, 249, 121, 217, 89 }, - { 15, 143, 47, 175, 7, 135, 39, 167, - 13, 141, 45, 173, 5, 133, 37, 165 }, - { 207, 79, 239, 111, 199, 71, 231, 103, - 205, 77, 237, 109, 197, 69, 229, 101 }, - { 63, 191, 31, 159, 55, 183, 23, 151, - 61, 189, 29, 157, 53, 181, 21, 149 }, - { 254, 127, 223, 95, 247, 119, 215, 87, - 253, 125, 221, 93, 245, 117, 213, 85 } - }; - - // Generate a 1-bit "screen door" alpha mask; not always pretty, but - // definitely fast... In the future we may be able to support things - // like the RENDER extension in XFree86, when available, to provide - // true RGBA-blended rendering. See: - // - // http://www.xfree86.org/~keithp/render/protocol.html - // - // for more info on XRender... - // - memset(bitmap, 0, bmw * h); - - for (dataptr = array + d - 1, y = 0; y < h; y ++, dataptr += ld) - for (bitptr = bitmap + y * bmw, bit = 1, x = 0; x < w; x ++, dataptr += d) { - if (*dataptr > dither[x & 15][y & 15]) - *bitptr |= bit; - if (bit < 128) bit <<= 1; - else { - bit = 1; - bitptr ++; - } - } - - bm = create_bitmask(w, h, bitmap); - delete[] bitmap; - - return bm; -} - - -void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img) -{ - Fl_Image_Surface *surface = new Fl_Image_Surface(img->data_w(), img->data_h()); - Fl_Surface_Device::push_current(surface); - if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { - fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); - } else { - fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d(), img->ld()); - if (img->d() == 2 || img->d() == 4) { - *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)create_alphamask(img->data_w(), img->data_h(), img->d(), img->ld(), img->array); - } - } - Fl_Surface_Device::pop_current(); - Fl_Offscreen offs = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surface); - int *pw, *ph; - cache_w_h(img, pw, ph); - *pw = img->data_w(); - *ph = img->data_h(); - *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)offs; -} - - -void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { - X = this->floor(X); - Y = this->floor(Y); - cache_size(img, W, H); - cx = this->floor(cx); cy = this->floor(cy); - if (W + cx > img->data_w()) W = img->data_w() - cx; - if (H + cy > img->data_h()) H = img->data_h() - cy; - if (!*Fl_Graphics_Driver::id(img)) { - cache(img); - } - if (*Fl_Graphics_Driver::mask(img)) { - HDC new_gc = CreateCompatibleDC(gc_); - int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)*Fl_Graphics_Driver::mask(img)); - BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCAND); - SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(img)); - BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCPAINT); - RestoreDC(new_gc,save); - DeleteDC(new_gc); - } else if (img->d()==2 || img->d()==4) { - copy_offscreen_with_alpha(X, Y, W, H, (HBITMAP)*Fl_Graphics_Driver::id(img), cx, cy); - } else { - copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy); - } -} - - -void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { - if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { - return; - } - if ((rgb->d() % 2) == 0 && !fl_can_do_alpha_blending()) { - Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy); - return; - } - if (!*Fl_Graphics_Driver::id(rgb)) { - cache(rgb); - } - push_clip(XP, YP, WP, HP); - XP -= cx; YP -= cy; - WP = rgb->w(); HP = rgb->h(); - cache_size(rgb, WP, HP); - HDC new_gc = CreateCompatibleDC(gc_); - int save = SaveDC(new_gc); - SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb)); - if ( (rgb->d() % 2) == 0 ) { - alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h()); - } else { - SetStretchBltMode(gc_, (Fl_Image::scaling_algorithm() == FL_RGB_SCALING_BILINEAR ? HALFTONE : BLACKONWHITE)); - StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY); - } - RestoreDC(new_gc, save); - DeleteDC(new_gc); - pop_clip(); -} - - -void Fl_GDI_Printer_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { - if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { - return; - } - XFORM old_tr, tr; - GetWorldTransform(gc_, &old_tr); // storing old transform - tr.eM11 = float(rgb->w())/float(rgb->data_w()); - tr.eM22 = float(rgb->h())/float(rgb->data_h()); - tr.eM12 = tr.eM21 = 0; - tr.eDx = float(XP); - tr.eDy = float(YP); - ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY); - if (*id(rgb)) { - int *pw, *ph; - cache_w_h(rgb, pw, ph); - if ( *pw != rgb->data_w() || *ph != rgb->data_h()) rgb->uncache(); - } - if (!*id(rgb)) cache(rgb); - draw_fixed(rgb, 0, 0, int(WP / tr.eM11), int(HP / tr.eM22), int(cx / tr.eM11), int(cy / tr.eM22)); - SetWorldTransform(gc_, &old_tr); -} - - -void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) -{ - if (id_) { - DeleteObject((HBITMAP)id_); - id_ = 0; - } - - if (mask_) { - delete_bitmask(mask_); - mask_ = 0; - } -} - -// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing... -static HBITMAP fl_create_bitmap(int w, int h, const uchar *data) { - // we need to pad the lines out to words & swap the bits - // in each byte. - int w1 = (w + 7) / 8; - int w2 = ((w + 15) / 16) * 2; - uchar* newarray = new uchar[w2*h]; - const uchar* src = data; - uchar* dest = newarray; - HBITMAP bm; - static uchar reverse[16] = /* Bit reversal lookup table */ - { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, - 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; - - for (int y = 0; y < h; y++) { - for (int n = 0; n < w1; n++, src++) - *dest++ = (uchar)((reverse[*src & 0x0f] & 0xf0) | - (reverse[(*src >> 4) & 0x0f] & 0x0f)); - dest += w2 - w1; - } - - bm = CreateBitmap(w, h, 1, 1, newarray); - - delete[] newarray; - - return bm; -} - -void Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) { - int *pw, *ph; - cache_w_h(bm, pw, ph); - *pw = bm->data_w(); - *ph = bm->data_h(); - *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)fl_create_bitmap(bm->data_w(), bm->data_h(), bm->array); -} - -void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) { - X = this->floor(X); - Y = this->floor(Y); - cache_size(pxm, W, H); - cx = this->floor(cx); cy = this->floor(cy); - Fl_Region r2 = scale_clip(scale()); - if (*Fl_Graphics_Driver::mask(pxm)) { - HDC new_gc = CreateCompatibleDC(gc_); - int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)*Fl_Graphics_Driver::mask(pxm)); - BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCAND); - SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm)); - BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCPAINT); - RestoreDC(new_gc,save); - DeleteDC(new_gc); - } else { - float s = scale(); Fl_Graphics_Driver::scale(1); - copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy); - Fl_Graphics_Driver::scale(s); - } - unscale_clip(r2); -} - -/* ===== Implementation note about how Fl_Pixmap objects get printed under Windows ===== - Fl_Pixmap objects are printed with the print-specific Fl_GDI_Printer_Graphics_Driver - which uses the TransparentBlt() system function that can scale the image and treat one - of its colors as transparent. - Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *,...) sets need_pixmap_bg_color, - a static class variable, to 1 and recaches the image. This calls fl_convert_pixmap() - that checks the value of need_pixmap_bg_color. When this value is not 0, fl_convert_pixmap - runs in a way that memorizes the list of all colors in the pixmap, computes - a color absent from this list, uses it for the transparent pixels of the pixmap and puts - this color value in need_pixmap_bg_color. As a result, the transparent areas of the image - are correcty handled by the printing operation. Variable need_pixmap_bg_color is ultimately - reset to 0. - Fl_GDI_Graphics_Driver::make_unused_color_() which does the color computation mentioned - above is implemented in file src/fl_draw_pixmap.cxx - */ -void Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; - transparent_f_type fl_TransparentBlt = TransparentBlt(); - if (fl_TransparentBlt) { - need_pixmap_bg_color = 1; - pxm->uncache(); - cache(pxm); - HDC new_gc = CreateCompatibleDC(gc_); - int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm)); - // print all of offscreen but its parts in background color - float scaleW = pxm->data_w()/float(pxm->w()); - float scaleH = pxm->data_h()/float(pxm->h()); - fl_TransparentBlt(gc_, X, Y, W, H, new_gc, - int(cx * scaleW), int(cy * scaleH), int(W * scaleW), int(H * scaleH), need_pixmap_bg_color ); - RestoreDC(new_gc,save); - DeleteDC(new_gc); - need_pixmap_bg_color = 0; - } - else { - copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy); - } -} - -// Makes an RGB triplet different from all the colors used in the pixmap -// and computes Fl_Graphics_Driver::need_pixmap_bg_color from this triplet -void Fl_GDI_Graphics_Driver::make_unused_color_(uchar &r, uchar &g, uchar &b, int color_count, void **data) { - typedef struct { uchar r; uchar g; uchar b; } UsedColor; - UsedColor *used_colors = *(UsedColor**)data; - int i; - r = 2; g = 3; b = 4; - while (1) { - for ( i=0; i<color_count; i++ ) - if ( used_colors[i].r == r && - used_colors[i].g == g && - used_colors[i].b == b ) - break; - if (i >= color_count) { - free((void*)used_colors); - *(UsedColor**)data = NULL; - need_pixmap_bg_color = RGB(r, g, b); - return; - } - if (r < 255) { - r++; - } else { - r = 0; - if (g < 255) { - g++; - } else { - g = 0; - b++; - } - } - } -} - -void Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img) { - Fl_Image_Surface *surf = new Fl_Image_Surface(img->data_w(), img->data_h()); - Fl_Surface_Device::push_current(surf); - uchar **pbitmap = surf->driver()->mask_bitmap(); - *pbitmap = (uchar*)1;// will instruct fl_draw_pixmap() to compute the image's mask - fl_draw_pixmap(img->data(), 0, 0, FL_BLACK); - uchar *bitmap = *pbitmap; - if (bitmap) { - *Fl_Graphics_Driver::mask(img) = - (fl_uintptr_t)create_bitmask(img->data_w(), img->data_h(), bitmap); - delete[] bitmap; - } - *pbitmap = 0; - Fl_Surface_Device::pop_current(); - Fl_Offscreen id = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf); - int *pw, *ph; - cache_w_h(img, pw, ph); - *pw = img->data_w(); - *ph = img->data_h(); - *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)id; -} - -void Fl_GDI_Graphics_Driver::uncache_pixmap(fl_uintptr_t offscreen) { - DeleteObject((HBITMAP)offscreen); -} diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx deleted file mode 100644 index 9d086f353..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx +++ /dev/null @@ -1,111 +0,0 @@ -// -// Line style code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -/** - \file Fl_GDI_Graphics_Driver_line_style.cxx - - \brief Line style drawing utility for Windows (GDI) platform. -*/ - -#include <FL/Fl.H> -#include <FL/platform.H> -#include <FL/fl_draw.H> - -#include "Fl_GDI_Graphics_Driver.H" - - -void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) { - - // 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 const DWORD Cap[4] = {PS_ENDCAP_FLAT, PS_ENDCAP_FLAT, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE}; - static const 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 = int(scale()); // fix cards that do nothing for 0? - if (!width) width = 1; - if (!fl_current_xmap) color(FL_BLACK); - 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(gc_, newpen); - DeleteObject(oldpen); - DeleteObject(fl_current_xmap->pen); - fl_current_xmap->pen = newpen; - style_ = style; -} - -#if USE_GDIPLUS - -void Fl_GDIplus_Graphics_Driver::line_style(int style, int width, char* dashes) { - if (!active) return Fl_Scalable_Graphics_Driver::line_style(style, width, dashes); - int gdi_width = (width ? width : 1); - pen_->SetWidth(Gdiplus::REAL(gdi_width)); - int standard_dash = style & 0x7; - if (standard_dash == FL_DASH ) - pen_->SetDashStyle(Gdiplus::DashStyleDash); - else if (standard_dash == FL_DOT ) - pen_->SetDashStyle(Gdiplus::DashStyleDot); - else if (standard_dash == FL_DASHDOT ) - pen_->SetDashStyle(Gdiplus::DashStyleDashDot); - else if (standard_dash == FL_DASHDOTDOT ) - pen_->SetDashStyle(Gdiplus::DashStyleDashDotDot); - else if(!dashes || !*dashes) - pen_->SetDashStyle(Gdiplus::DashStyleSolid); - - if (style & FL_CAP_ROUND ) { - pen_->SetStartCap(Gdiplus::LineCapRound); - pen_->SetEndCap(Gdiplus::LineCapRound); - } else if (style & FL_CAP_SQUARE ) { - pen_->SetStartCap(Gdiplus::LineCapSquare); - pen_->SetEndCap(Gdiplus::LineCapSquare); - } else { - pen_->SetStartCap(Gdiplus::LineCapFlat); - pen_->SetEndCap(Gdiplus::LineCapFlat); - } - - if (style & FL_JOIN_MITER ) { - pen_->SetLineJoin(Gdiplus::LineJoinMiter); - } else if (style & FL_JOIN_BEVEL ) { - pen_->SetLineJoin(Gdiplus::LineJoinBevel); - } else { - pen_->SetLineJoin(Gdiplus::LineJoinRound); - } - - if (dashes && *dashes) { - int n = 0; while (dashes[n]) n++; - Gdiplus::REAL *gdi_dashes = new Gdiplus::REAL[n]; - for (int i = 0; i < n; i++) gdi_dashes[i] = dashes[i]/float(gdi_width); - pen_->SetDashPattern(gdi_dashes, n); - delete[] gdi_dashes; - } - Fl_Scalable_Graphics_Driver::line_style(style, width, dashes); -} - -#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx deleted file mode 100644 index a86242e12..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx +++ /dev/null @@ -1,320 +0,0 @@ -// -// Rectangle drawing routines for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - - -/** - \file Fl_GDI_Graphics_Driver_rect.cxx - \brief Windows GDI specific line and polygon drawing with integer coordinates. - */ - -#include <config.h> -#include <FL/Fl.H> -#include <FL/Fl_Widget.H> -#include <FL/fl_draw.H> -#include <FL/platform.H> - -#include "Fl_GDI_Graphics_Driver.H" - - -// --- line and polygon drawing with integer coordinates - -void Fl_GDI_Graphics_Driver::point(int x, int y) { - rectf(x, y, 1, 1); -} - -void Fl_GDI_Graphics_Driver::overlay_rect(int x, int y, int w , int h) { - // make pen have a one-pixel width - line_style_unscaled( (color()==FL_WHITE?FL_SOLID:FL_DOT), 1, NULL); - int right = this->floor(x+w-1), bottom = this->floor(y+h-1); - x = this->floor(x); y = this->floor(y); - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, right, y); - LineTo(gc_, right, bottom); - LineTo(gc_, x, bottom); - LineTo(gc_, x, y); -} - -void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) { - // Windows 95/98/ME do not implement the dotted line style, so draw - // every other pixel around the focus area... - w = floor(x+w-1) - floor(x) + 1; - h = floor(y+h-1) - floor(y) + 1; - x = floor(x); y = floor(y); - int i=1, xx, yy; - COLORREF c = fl_RGB(); - for (xx = 0; xx < w; xx++, i++) if (i & 1) SetPixel(gc_, x+xx, y, c); - for (yy = 0; yy < h; yy++, i++) if (i & 1) SetPixel(gc_, x+w, y+yy, c); - for (xx = w; xx > 0; xx--, i++) if (i & 1) SetPixel(gc_, x+xx, y+h, c); - for (yy = h; yy > 0; yy--, i++) if (i & 1) SetPixel(gc_, x, y+yy, c); -} - -void Fl_GDI_Graphics_Driver::rect_unscaled(int x, int y, int w, int h) { - if (is_solid_ && line_width_ > 1) { - line_style_unscaled(FL_CAP_SQUARE, line_width_, 0); // see issue #1052 - } - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x+w, y); - if (is_solid_ && line_width_ <= 1) LineTo(gc_, x+w, y+h+1); // see issue #1052 - LineTo(gc_, x+w, y+h); - LineTo(gc_, x, y+h); - LineTo(gc_, x, y); - if (is_solid_ && line_width_ > 1) { - line_style_unscaled(style_, line_width_, 0); - } -} - -void Fl_GDI_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) { - RECT rect; - rect.left = x; rect.top = y; - rect.right = (x + w); rect.bottom = (y + h); - FillRect(gc_, &rect, fl_brush()); -} - -void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) { - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x1, y1); - SetPixel(gc_, x1, y1, fl_RGB()); -} - -void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) { - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x1, y1); - LineTo(gc_, x2, y2); - SetPixel(gc_, x2, y2, fl_RGB()); -} - -void* Fl_GDI_Graphics_Driver::change_pen_width(int width) { // set the width of the pen, return previous pen - LOGBRUSH penbrush = {BS_SOLID, fl_RGB(), 0}; - HPEN newpen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, width, &penbrush, 0, 0); - return SelectObject(gc_, newpen); -} - -void Fl_GDI_Graphics_Driver::reset_pen_width(void *data) { - DeleteObject(SelectObject(gc_, (HPEN)data)); -} - -void Fl_GDI_Graphics_Driver::xyline_unscaled(int x, int y, int x1) { - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x1+1 , y); -} - -void Fl_GDI_Graphics_Driver::yxline_unscaled(int x, int y, int y1) { - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x, y1+1); -} - -void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2) { - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x1, y1); - LineTo(gc_, x2, y2); - LineTo(gc_, x, y); -} - -void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { - MoveToEx(gc_, x, y, 0L); - LineTo(gc_, x1, y1); - LineTo(gc_, x2, y2); - LineTo(gc_, x3, y3); - LineTo(gc_, x, y); -} - -void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2) { - POINT 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(gc_, fl_brush()); - Polygon(gc_, p, 3); -} - -void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { - POINT 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(gc_, fl_brush()); - Polygon(gc_, p, 4); -} - -// --- clipping - -void Fl_GDI_Graphics_Driver::push_clip(int x, int y, int w, int h) { - HRGN r; - if (w > 0 && h > 0) { - r = (HRGN)XRectangleRegion(x,y,w,h); - HRGN current = (HRGN)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; - HRGN r = (HRGN)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... - HRGN rr = (HRGN)XRectangleRegion(x,y,w,h); - HRGN 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(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; - HRGN r = (HRGN)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(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); -} - -void Fl_GDI_Graphics_Driver::restore_clip() { - fl_clip_state_number++; - if (gc_) { - HRGN r = NULL; - if (rstack[rstackptr]) r = (HRGN)scale_clip(scale()); - SelectClipRgn(gc_, (HRGN)rstack[rstackptr]); // if region is NULL, clip is automatically cleared - if (r) unscale_clip(r); - } -} - -#if USE_GDIPLUS - -void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1) { - if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1); - bool AA = !(x == x1 || y == y1); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - pen_->SetColor(gdiplus_color_); - if (AA) graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.DrawLine(pen_, x, y, x1, y1); -} - -void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { - if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1, x2, y2); - line(x, y, x1, y1); - line(x1, y1, x2, y2); -} - -void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { - if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2); - Gdiplus::GraphicsPath path; - Gdiplus::Point gdi2_p[3] = {Gdiplus::Point(x0, y0), Gdiplus::Point(x1, y1), Gdiplus::Point(x2, y2)}; - path.AddLines(gdi2_p, 3); - path.CloseFigure(); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - pen_->SetColor(gdiplus_color_); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.DrawPath(pen_, &path); -} - -#define fl_min(a,b) (a < b ? a : b) -#define fl_max(a,b) (a > b ? a : b) -void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { - if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) || - (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { // rectangular loop - int left = fl_min(x0, fl_min(x1, fl_min(x2, x3))); - int right = fl_max(x0, fl_max(x1, fl_max(x2, x3))); - int top = fl_min(y0, fl_min(y1, fl_min(y2, y3))); - int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3))); - rect(left, top, right-left+1, bottom-top+1); - } else { - if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2, x3, y3); - Gdiplus::GraphicsPath path; - Gdiplus::PointF gdi2_p[4] = {Gdiplus::PointF(x0+1-line_width_/2.f, y0+1-line_width_/2.f), Gdiplus::PointF(x1+1-line_width_/2.f, y1+1-line_width_/2.f), Gdiplus::PointF(x2+1-line_width_/2.f, y2+1-line_width_/2.f), Gdiplus::PointF(x3+1-line_width_/2.f, y3+1-line_width_/2.f)}; - path.AddLines(gdi2_p, 4); - path.CloseFigure(); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - pen_->SetColor(gdiplus_color_); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.DrawPath(pen_, &path); - } -} - -void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { - if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2); - Gdiplus::GraphicsPath path; - path.AddLine(x0, y0, x1, y1); - path.AddLine(x1, y1, x2, y2); - path.CloseFigure(); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - brush_->SetColor(gdiplus_color_); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.FillPath(brush_, &path); -} - -void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { - if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) || - (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { - int left = fl_min(x0, fl_min(x1, fl_min(x2, x3))); - int right = fl_max(x0, fl_max(x1, fl_max(x2, x3))); - int top = fl_min(y0, fl_min(y1, fl_min(y2, y3))); - int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3))); - rectf(left, top, right-left, bottom-top); - } else { - if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2, x3, y3); - Gdiplus::GraphicsPath path; - path.AddLine(x0, y0, x1, y1); - path.AddLine(x1, y1, x2, y2); - path.AddLine(x2, y2, x3, y3); - path.CloseFigure(); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - brush_->SetColor(gdiplus_color_); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - graphics_.FillPath(brush_, &path); - } -} -#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx deleted file mode 100644 index e469bb11b..000000000 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx +++ /dev/null @@ -1,231 +0,0 @@ -// -// Portable drawing routines for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -/** - \file Fl_GDI_Graphics_Driver_vertex.cxx - - \brief Portable drawing code for drawing arbitrary shapes with - simple 2D transformations, implemented for Windows GDI. -*/ - -#include "Fl_GDI_Graphics_Driver.H" - -#include <FL/fl_draw.H> -#include <FL/platform.H> -#include <FL/math.h> - - -void Fl_GDI_Graphics_Driver::end_points() { - for (int i=0; i<n; i++) SetPixel(gc_, long_point[i].x, long_point[i].y, fl_RGB()); -} - -void Fl_GDI_Graphics_Driver::end_line() { - if (n < 2) { - end_points(); - return; - } - if (n>1) Polyline(gc_, long_point, n); -} - -void Fl_GDI_Graphics_Driver::end_loop() { - fixloop(); - if (n>2) transformed_vertex0(float(long_point[0].x), float(long_point[0].y)); - end_line(); -} - -void Fl_GDI_Graphics_Driver::end_polygon() { - fixloop(); - if (n < 3) { - end_line(); - return; - } - if (n>2) { - SelectObject(gc_, fl_brush()); - Polygon(gc_, long_point, n); - } -} - -void Fl_GDI_Graphics_Driver::begin_complex_polygon() { - Fl_Graphics_Driver::begin_complex_polygon(); - numcount = 0; -} - -void Fl_GDI_Graphics_Driver::gap() { - while (n>gap_+2 && long_point[n-1].x == long_point[gap_].x && long_point[n-1].y == long_point[gap_].y) n--; - if (n > gap_+2) { - transformed_vertex0(float(long_point[gap_].x), float(long_point[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(gc_, fl_brush()); - PolyPolygon(gc_, long_point, counts, numcount); - } -} - -void Fl_GDI_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) { - 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(gc_, fl_brush()); - Pie(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0); - } else - Arc(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0); -} - -#if USE_GDIPLUS - -void Fl_GDIplus_Graphics_Driver::transformed_vertex(double xf, double yf) { - if (!active) return Fl_Scalable_Graphics_Driver::transformed_vertex(xf, yf); - transformed_vertex0(float(xf) , float(yf) ); -} - -void Fl_GDIplus_Graphics_Driver::vertex(double x,double y) { - if (!active) return Fl_Scalable_Graphics_Driver::vertex(x, y); - transformed_vertex0(float(x*m.a + y*m.c + m.x) , float(x*m.b + y*m.d + m.y) ); -} - -void Fl_GDIplus_Graphics_Driver::end_points() { - if (!active) return Fl_GDI_Graphics_Driver::end_points(); - for (int i = 0; i < n; i++) point(long_point[i].x, long_point[i].y); -} - -void Fl_GDIplus_Graphics_Driver::end_line() { - if (!active) return Fl_GDI_Graphics_Driver::end_line(); - if (n < 2) { - end_points(); - return; - } - if (n>1) { - Gdiplus::GraphicsPath path; - Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; - for (int i = 0; i < n; i++) { - gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); - } - path.AddLines(gdi2_p, n); - delete[] gdi2_p; - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - pen_->SetColor(gdiplus_color_); - graphics_.DrawPath(pen_, &path); - } -} - -void Fl_GDIplus_Graphics_Driver::end_loop() { - if (!active) return Fl_GDI_Graphics_Driver::end_loop(); - fixloop(); - if (n >= 2) { - Gdiplus::GraphicsPath path; - Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; - for (int i = 0; i < n; i++) { - gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); - } - path.AddLines(gdi2_p, n); - path.CloseFigure(); - delete[] gdi2_p; - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - pen_->SetColor(gdiplus_color_); - graphics_.DrawPath(pen_, &path); - } -} - -void Fl_GDIplus_Graphics_Driver::end_polygon() { - if (!active) return Fl_GDI_Graphics_Driver::end_polygon(); - fixloop(); - if (n < 3) { - end_line(); - return; - } - if (n>2) { - Gdiplus::GraphicsPath path; - Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; - for (int i = 0; i < n; i++) { - gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); - } - path.AddPolygon(gdi2_p, n); - delete[] gdi2_p; - path.CloseFigure(); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - brush_->SetColor(gdiplus_color_); - graphics_.FillPath(brush_, &path); - } -} - -void Fl_GDIplus_Graphics_Driver::end_complex_polygon() { - if (!active) return Fl_GDI_Graphics_Driver::end_complex_polygon(); - gap(); - if (n < 3) { - end_line(); - return; - } - if (n>2) { - Gdiplus::GraphicsPath path; - Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; - for (int i = 0; i < n; i++) { - gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); - } - path.AddPolygon(gdi2_p, n); - delete[] gdi2_p; - path.CloseFigure(); - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - brush_->SetColor(gdiplus_color_); - graphics_.FillPath(brush_, &path); - } -} - -void Fl_GDIplus_Graphics_Driver::circle(double x, double y, double r) { - if (!active) return Fl_Scalable_Graphics_Driver::circle(x, y, r); - double xt = transform_x(x,y); - double yt = transform_y(x,y); - double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); - double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); - int llx = (int)rint(xt-rx); - int w = (int)rint(xt+rx)-llx; - int lly = (int)rint(yt-ry); - int h = (int)rint(yt+ry)-lly; - Gdiplus::Graphics graphics_(gc_); - graphics_.ScaleTransform(scale(), scale()); - graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - if (what==POLYGON) { - brush_->SetColor(gdiplus_color_); - graphics_.FillPie(brush_, llx, lly, w, h, 0, 360); - } else { - pen_->SetColor(gdiplus_color_); - graphics_.DrawArc(pen_, llx, lly, w, h, 0, 360); - } -} -#endif - diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H deleted file mode 100644 index 129a4ecbc..000000000 --- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H +++ /dev/null @@ -1,44 +0,0 @@ -// -// Draw-to-image code for the Fast Light Tool Kit (FLTK). -// -// Copyright 2022 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - -#ifndef FL_GDI_IMAGE_SURFACE_DRIVER_H -#define FL_GDI_IMAGE_SURFACE_DRIVER_H - -#include <FL/Fl_Image_Surface.H> -#include <FL/Fl_RGB_Image.H> -#include <FL/platform.H> - -class Fl_GDI_Image_Surface_Driver : public Fl_Image_Surface_Driver { - void end_current() FL_OVERRIDE; -public: - HWND pre_window; - int _savedc; - void mask(const Fl_RGB_Image *) FL_OVERRIDE; - struct shape_data_type { - HBITMAP background; - uchar *vBits; - Fl_RGB_Image* mask; - } *shape_data_; - Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); - ~Fl_GDI_Image_Surface_Driver(); - void set_current() FL_OVERRIDE; - void translate(int x, int y) FL_OVERRIDE; - void untranslate() FL_OVERRIDE; - Fl_RGB_Image *image() FL_OVERRIDE; - POINT origin; -}; - -#endif // FL_GDI_IMAGE_SURFACE_DRIVER_H diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx deleted file mode 100644 index a14524ee2..000000000 --- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx +++ /dev/null @@ -1,169 +0,0 @@ -// -// Draw-to-image code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2018 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: -// -// https://www.fltk.org/COPYING.php -// -// Please see the following page on how to report bugs and issues: -// -// https://www.fltk.org/bugs.php -// - - -#include "Fl_GDI_Graphics_Driver.H" -#include "../WinAPI/Fl_WinAPI_Screen_Driver.H" -#include "Fl_GDI_Image_Surface_Driver.H" -#include <FL/platform.H> -#include <FL/Fl_Bitmap.H> -#include <windows.h> - - -Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) { - Fl_Display_Device::display_device(); // make sure fl_graphics_driver was initialized - float d = fl_graphics_driver->scale(); - if (!off && d != 1 && high_res) { - w = int(w*d); - h = int(h*d); - } - HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); - offscreen = off ? off : (Fl_Offscreen)CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h); - if (!offscreen) offscreen = (Fl_Offscreen)CreateCompatibleBitmap(fl_GetDC(0), w, h); - driver(Fl_Graphics_Driver::newMainGraphicsDriver()); - if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d); - origin.x = origin.y = 0; - shape_data_ = NULL; -} - - -Fl_GDI_Image_Surface_Driver::~Fl_GDI_Image_Surface_Driver() { - if (shape_data_ && shape_data_->background) { - DeleteObject(shape_data_->background); - delete shape_data_->mask; - free(shape_data_); - } - if (offscreen && !external_offscreen) DeleteObject((HBITMAP)offscreen); - delete driver(); -} - - -void Fl_GDI_Image_Surface_Driver::set_current() { - HDC gc = fl_makeDC((HBITMAP)offscreen); - driver()->gc(gc); - SetWindowOrgEx(gc, origin.x, origin.y, NULL); - Fl_Surface_Device::set_current(); - pre_window = fl_window; - _savedc = SaveDC(gc); - fl_window=(HWND)offscreen; -} - - -void Fl_GDI_Image_Surface_Driver::translate(int x, int y) { - ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y); -} - - -void Fl_GDI_Image_Surface_Driver::untranslate() { - ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all(); -} - - -Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image() -{ - if (shape_data_ && shape_data_->background) { - // get the offscreen size in pixels - HDC gc = fl_makeDC((HBITMAP)offscreen); - BITMAPINFO bmi; - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 0; - bmi.bmiHeader.biSizeImage = 0; - GetDIBits(gc, (HBITMAP)offscreen, 0, 0, NULL, &bmi, DIB_RGB_COLORS); - int W = bmi.bmiHeader.biWidth; - int H = bmi.bmiHeader.biHeight; - int line_size = ((3*W+3)/4) * 4; - - // read bits of main offscreen - uchar *dib_src = new uchar[line_size * H]; - bmi.bmiHeader.biWidth = W; - bmi.bmiHeader.biHeight = H; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biBitCount = 24; - GetDIBits(gc, (HBITMAP)offscreen, 0, H, - dib_src, &bmi, DIB_RGB_COLORS); - - // draw above the secondary offscreen the main offscreen masked by shape_data_->mask - GdiFlush(); - Fl_Image_Surface_Driver::copy_with_mask(shape_data_->mask, shape_data_->vBits, dib_src, ((3*W+3)/4) * 4, true); - delete shape_data_->mask; - delete[] dib_src; - - // write bits of main offscreen - SetDIBits(gc, (HBITMAP)offscreen, 0, H, shape_data_->vBits, &bmi, DIB_RGB_COLORS); - DeleteDC(gc); - DeleteObject(shape_data_->background); - shape_data_->background = NULL; - free(shape_data_); - shape_data_ = NULL; - } - Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height, 0); - return image; -} - - -void Fl_GDI_Image_Surface_Driver::end_current() -{ - HDC gc = (HDC)driver()->gc(); - GetWindowOrgEx(gc, &origin); - RestoreDC(gc, _savedc); - DeleteDC(gc); - fl_window = pre_window; - Fl_Surface_Device::end_current(); -} - - -void Fl_GDI_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) { - shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type)); - // get the offscreen size in pixels - HDC gc = fl_makeDC((HBITMAP)offscreen); - BITMAPINFO bmi; - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 0; - bmi.bmiHeader.biSizeImage = 0; - - GetDIBits(gc, (HBITMAP)offscreen, 0, 0, NULL, &bmi, DIB_RGB_COLORS); - int W = bmi.bmiHeader.biWidth; - int H = bmi.bmiHeader.biHeight; - - shape_data_->mask = Fl_Image_Surface_Driver::RGB3_to_RGB1(mask, W, H); - - // duplicate current offscreen content to new offscreen - int line_size = ((3*W+3)/4) * 4; - uchar *dib = new uchar[line_size * H]; // create temporary buffer to read DIB - bmi.bmiHeader.biWidth = W; - bmi.bmiHeader.biHeight = H; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biBitCount = 24; - - GetDIBits(gc, (HBITMAP)offscreen, 0, H, dib, &bmi, DIB_RGB_COLORS); - - HDC background_gc = CreateCompatibleDC(gc); - shape_data_->background = - CreateDIBSection(background_gc, &bmi, DIB_RGB_COLORS, - (void**)&shape_data_->vBits, NULL, 0); - if (!shape_data_->background) { - Fl::error("CreateDIBSection error=%lu", GetLastError()); - } - memcpy(shape_data_->vBits, dib, H * line_size); - delete[] dib; - DeleteDC(background_gc); - DeleteDC(gc); -} - |
