diff options
| -rw-r--r-- | FL/Fl_Bitmap.H | 13 | ||||
| -rw-r--r-- | FL/Fl_Device.H | 255 | ||||
| -rw-r--r-- | FL/Fl_Graphics_Device.H | 411 | ||||
| -rw-r--r-- | FL/Fl_Graphics_Driver.H | 263 | ||||
| -rw-r--r-- | FL/Fl_Image.H | 22 | ||||
| -rw-r--r-- | FL/Fl_Pixmap.H | 27 | ||||
| -rw-r--r-- | FL/fl_draw.H | 2 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | src/Fl_Bitmap.cxx | 53 | ||||
| -rw-r--r-- | src/Fl_Device.cxx | 63 | ||||
| -rw-r--r-- | src/Fl_Graphics_Device.cxx | 106 | ||||
| -rw-r--r-- | src/Fl_Graphics_Driver.cxx | 69 | ||||
| -rw-r--r-- | src/Fl_Image.cxx | 236 | ||||
| -rw-r--r-- | src/Fl_Pixmap.cxx | 152 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.h | 6 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 188 | ||||
| -rw-r--r-- | src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h | 2 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h | 13 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx | 41 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h | 6 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 207 |
21 files changed, 1361 insertions, 787 deletions
diff --git a/FL/Fl_Bitmap.H b/FL/Fl_Bitmap.H index 4c8efb4d5..3bb6f23d1 100644 --- a/FL/Fl_Bitmap.H +++ b/FL/Fl_Bitmap.H @@ -21,7 +21,8 @@ #ifndef Fl_Bitmap_H #define Fl_Bitmap_H -# include "Fl_Image.H" +#include "Fl_Image.H" +#include "Fl_Widget.H" // for fl_uintptr_t class Fl_Widget; struct Fl_Menu_Item; @@ -45,16 +46,8 @@ public: private: int start(int XP, int YP, int WP, int HP, int &cx, int &cy, int &X, int &Y, int &W, int &H); -#if defined(__APPLE__) || defined(WIN32) /** for internal use */ - void *id_; -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define variables to hold a native bitmap in Fl_Bitmap" - unsigned id_; // default if not ported -#else - /** for internal use */ - unsigned id_; -#endif // __APPLE__ || WIN32 + fl_uintptr_t id_; public: diff --git a/FL/Fl_Device.H b/FL/Fl_Device.H index 5daf1a6bf..3bddc3f65 100644 --- a/FL/Fl_Device.H +++ b/FL/Fl_Device.H @@ -1,10 +1,10 @@ // // "$Id$" // -// Definition of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device +// Definition of classes Fl_Device, Fl_Surface_Device, Fl_Display_Device // for the Fast Light Tool Kit (FLTK). // -// Copyright 2010-2014 by Bill Spitzak and others. +// Copyright 2010-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -18,7 +18,7 @@ // /** \file Fl_Device.H - \brief declaration of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, + \brief declaration of classes Fl_Device, Fl_Surface_Device, Fl_Display_Device, Fl_Device_Plugin. */ @@ -27,45 +27,10 @@ #include <FL/x.H> #include <FL/Fl_Plugin.H> -#include <FL/Fl_Image.H> -#include <FL/Fl_Bitmap.H> -#include <FL/Fl_Pixmap.H> -#include <FL/Fl_RGB_Image.H> #include <stdlib.h> class Fl_Graphics_Driver; class Fl_Font_Descriptor; -/** \brief Points to the driver that currently receives all graphics requests */ -FL_EXPORT extern Fl_Graphics_Driver *fl_graphics_driver; - -/** - signature of image generation callback function. - \param[in] data user data passed to function - \param[in] x,y,w position and width of scan line in image - \param[out] buf buffer for generated image data. You must copy \p w - pixels from scanline \p y, starting at pixel \p x - to this buffer. - */ -typedef void (*Fl_Draw_Image_Cb)(void* data,int x,int y,int w,uchar* buf); - -// typedef what the x,y fields in a point are: -#ifdef WIN32 -typedef int COORD_T; -# define XPOINT XPoint -#elif defined(__APPLE__) -typedef float COORD_T; -typedef struct { float x; float y; } QPoint; -# define XPOINT QPoint -extern float fl_quartz_line_width_; -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define types for COORD_T and XPOINT" -typedef int COORD_T; // default if not ported -typedef struct { int x; int y; } QPoint; -# define XPOINT QPoint -#else -typedef short COORD_T; -# define XPOINT XPoint -#endif /** All graphical output devices and all graphics systems. @@ -96,220 +61,6 @@ public: virtual ~Fl_Device() {}; }; -#define FL_REGION_STACK_SIZE 10 -#define FL_MATRIX_STACK_SIZE 32 -/** - \brief A virtual class subclassed for each graphics driver FLTK uses. - Typically, FLTK applications do not use directly objects from this class. Rather, they perform - drawing operations (e.g., fl_rectf()) that operate on the current drawing surface (see Fl_Surface_Device). - Drawing operations are functionally presented in \ref drawing and as function lists - in the \ref fl_drawings and \ref fl_attributes modules. The \ref fl_graphics_driver global variable - gives at any time the graphics driver used by all drawing operations. Its value changes when - drawing operations are directed to another drawing surface by Fl_Surface_Device::set_current(). - - \p The Fl_Graphics_Driver class is of interest if one wants to perform new kinds of drawing operations. - An example would be to draw to a PDF file. This would involve creating a new Fl_Graphics_Driver derived - class. This new class should implement all virtual methods of the Fl_Graphics_Driver class - to support all FLTK drawing functions. - */ -class FL_EXPORT Fl_Graphics_Driver : public Fl_Device { - friend class Fl_Pixmap; - friend class Fl_Bitmap; - friend class Fl_RGB_Image; -public: - // The following functions create the various graphics drivers that are required - // for core operations. They must be implemented as members of Fl_Graphics_Driver, - // but located in the device driver module that is linked to the core library - static Fl_Graphics_Driver *newMainGraphicsDriver(); - //static Fl_Graphics_Driver *newOpenGLGraphicsDriver(); - //static Fl_Graphics_Driver *newPrinterGraphicsDriver(); - //static Fl_Graphics_Driver *new...; -public: - /** A 2D coordinate transformation matrix */ - struct matrix {double a, b, c, d, x, y;}; - /** Features that a derived class may possess. */ - typedef enum { - NATIVE = 1, /**< native graphics driver for the platform */ - PRINTER = 2 /**< graphics driver for a printer drawing surface */ - } driver_feature; - - int fl_clip_state_number; -protected: - static const matrix m0; - Fl_Font font_; // current font - Fl_Fontsize size_; // current font size - Fl_Color color_; // current color - int sptr; - static const int matrix_stack_size = FL_MATRIX_STACK_SIZE; - matrix stack[FL_MATRIX_STACK_SIZE]; - matrix m; - int n, p_size, gap_; - XPOINT *p; - int what; - int rstackptr; - static const int region_stack_max = FL_REGION_STACK_SIZE - 1; - Fl_Region rstack[FL_REGION_STACK_SIZE]; - Fl_Font_Descriptor *font_descriptor_; -#ifndef FL_DOXYGEN - enum {LINE, LOOP, POLYGON, POINT_}; - inline int vertex_no() { return n; } - inline XPOINT *vertices() {return p;} - inline int vertex_kind() {return what;} -#endif - matrix *fl_matrix; /**< Points to the current coordinate transformation matrix */ - - // === all code below in this class has been to the reorganisation FL_PORTING process -public: - static const char *class_id; - virtual const char *class_name() {return class_id;}; - Fl_Graphics_Driver(); - virtual ~Fl_Graphics_Driver() { if (p) free(p); } -public: - // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx - virtual void point(int x, int y) = 0; - virtual void rect(int x, int y, int w, int h) = 0; - virtual void focus_rect(int x, int y, int w, int h); - virtual void rectf(int x, int y, int w, int h) = 0; - virtual void line(int x, int y, int x1, int y1) = 0; - virtual void line(int x, int y, int x1, int y1, int x2, int y2) = 0; - virtual void xyline(int x, int y, int x1) = 0; - virtual void xyline(int x, int y, int x1, int y2) = 0; - virtual void xyline(int x, int y, int x1, int y2, int x3) = 0; - virtual void yxline(int x, int y, int y1) = 0; - virtual void yxline(int x, int y, int y1, int x2) = 0; - virtual void yxline(int x, int y, int y1, int x2, int y3) = 0; - virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) = 0; - virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; - virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) = 0; - virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; - // --- clipping - virtual void push_clip(int x, int y, int w, int h) = 0; - virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) = 0; - virtual int not_clipped(int x, int y, int w, int h) = 0; - virtual void push_no_clip() = 0; - virtual void pop_clip() = 0; - virtual Fl_Region clip_region(); // has default implementation - virtual void clip_region(Fl_Region r); // has default implementation - virtual void restore_clip(); - // --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx - virtual void push_matrix(); - virtual void pop_matrix(); - virtual void mult_matrix(double a, double b, double c, double d, double x, double y); - virtual void rotate(double d); - virtual void scale(double x, double y); - virtual void scale(double x); - virtual void translate(double x,double y); - virtual void begin_points(); - virtual void begin_line(); - virtual void begin_loop(); - virtual void begin_polygon(); - virtual void begin_complex_polygon() = 0; - virtual double transform_x(double x, double y); - virtual double transform_y(double x, double y); - virtual double transform_dx(double x, double y); - virtual double transform_dy(double x, double y); - virtual void transformed_vertex(double xf, double yf) = 0; - virtual void vertex(double x, double y) = 0; - virtual void end_points() = 0; - virtual void end_line() = 0; - virtual void end_loop() = 0; - virtual void end_polygon() = 0; - virtual void end_complex_polygon() = 0; - virtual void gap() = 0; - virtual void circle(double x, double y, double r) = 0; - // --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed - virtual void arc(double x, double y, double r, double start, double end); - // --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx - virtual void arc(int x, int y, int w, int h, double a1, double a2) = 0; - virtual void pie(int x, int y, int w, int h, double a1, double a2) = 0; - // --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed - virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3); - // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx - virtual void line_style(int style, int width=0, char* dashes=0) = 0; - // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx - virtual void color(Fl_Color c) { color_ = c; } - virtual Fl_Color color() { return color_; } - virtual void color(uchar r, uchar g, uchar b) = 0; - // --- implementation is in src/fl_font.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx - virtual void draw(const char *str, int n, int x, int y) = 0; - virtual void draw(const char *str, int n, float x, float y) { draw(str, n, (int)(x+0.5), (int)(y+0.5));} - virtual void draw(int angle, const char *str, int n, int x, int y) { draw(str, n, x, y); } - virtual void rtl_draw(const char *str, int n, int x, int y) { draw(str, n, x, y); } - /** Returns non-zero if the graphics driver possesses the \p feature */ - virtual int has_feature(driver_feature feature) { return 0; } - virtual void font(Fl_Font face, Fl_Fontsize fsize) {font_ = face; size_ = fsize;} - virtual Fl_Font font() {return font_; } - virtual Fl_Fontsize size() {return size_; } - virtual double width(const char *str, int n) { return 0; } - virtual double width(unsigned int c) { char ch = (char)c; return width(&ch, 1); } - virtual void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); - virtual int height() { return size(); } - virtual int descent() { return 0; } - virtual Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;} - virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;} - // --- implementation is in src/fl_image.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx - virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) = 0; - virtual void delete_bitmask(Fl_Bitmask bm) = 0; - virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) {} - virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) {} - virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) {} - virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) {} - /** \brief Draws an Fl_RGB_Image object to the device. - * - Specifies a bounding box for the image, with the origin (upper left-hand corner) of - the image offset by the cx and cy arguments. - */ - virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) {} - /** \brief Draws an Fl_Pixmap object to the device. - * - Specifies a bounding box for the image, with the origin (upper left-hand corner) of - the image offset by the cx and cy arguments. - */ - virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) {} - /** \brief Draws an Fl_Bitmap object to the device. - * - Specifies a bounding box for the image, with the origin (upper left-hand corner) of - the image offset by the cx and cy arguments. - */ - virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {} - virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H); - virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); - -protected: - // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx - virtual void transformed_vertex0(COORD_T x, COORD_T y); - virtual void fixloop(); -}; - - - -#if defined(__APPLE__) - -#elif defined(WIN32) || defined(FL_DOXYGEN) - -#if FL_LIBRARY -#include "src/drivers/GDI/Fl_GDI_Graphics_Driver.h" -#endif - -#elif defined(FL_PORTING) - -# pragma message "FL_PORTING: define a native graphics driver Fl_xxx_Graphics_Driver" -class FL_EXPORT Fl_XXX_Graphics_Driver : public Fl_Graphics_Driver { -protected: - // --- recently moved implementations (see FL_PORTING efforts) - void point(int x, int y) { } - void rect(int x, int y, int w, int h) { } -}; - -#else // X11 - -#if FL_LIBRARY -#include "src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h" -#endif - -#endif - - /** A drawing surface that's susceptible to receive graphical output. diff --git a/FL/Fl_Graphics_Device.H b/FL/Fl_Graphics_Device.H new file mode 100644 index 000000000..35315146b --- /dev/null +++ b/FL/Fl_Graphics_Device.H @@ -0,0 +1,411 @@ +// +// "$Id$" +// +// Definition of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device +// for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/** \file Fl_Device.H + \brief declaration of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, + Fl_Display_Device, Fl_Device_Plugin. +*/ + +#ifndef Fl_Device_H +#define Fl_Device_H + +#include <FL/x.H> +#include <FL/Fl_Plugin.H> +#include <FL/Fl_Image.H> +#include <FL/Fl_Bitmap.H> +#include <FL/Fl_Pixmap.H> +#include <FL/Fl_RGB_Image.H> +#include <stdlib.h> + +class Fl_Graphics_Driver; +class Fl_Font_Descriptor; +/** \brief Points to the driver that currently receives all graphics requests */ +FL_EXPORT extern Fl_Graphics_Driver *fl_graphics_driver; + +/** + signature of image generation callback function. + \param[in] data user data passed to function + \param[in] x,y,w position and width of scan line in image + \param[out] buf buffer for generated image data. You must copy \p w + pixels from scanline \p y, starting at pixel \p x + to this buffer. + */ +typedef void (*Fl_Draw_Image_Cb)(void* data,int x,int y,int w,uchar* buf); + +// typedef what the x,y fields in a point are: +#ifdef WIN32 +typedef int COORD_T; +# define XPOINT XPoint +#elif defined(__APPLE__) +typedef float COORD_T; +typedef struct { float x; float y; } QPoint; +# define XPOINT QPoint +extern float fl_quartz_line_width_; +#elif defined(FL_PORTING) +# pragma message "FL_PORTING: define types for COORD_T and XPOINT" +typedef int COORD_T; // default if not ported +typedef struct { int x; int y; } QPoint; +# define XPOINT QPoint +#else +typedef short COORD_T; +# define XPOINT XPoint +#endif + +/** + All graphical output devices and all graphics systems. + This class supports a rudimentary system of run-time type information. + */ +class FL_EXPORT Fl_Device { +public: + /** A string that identifies each subclass of Fl_Device. + Function class_name() applied to a device of this class returns this string. + */ + static const char *class_id; + /** + Returns the name of the class of this object. + Use of the class_name() function is discouraged because it will be removed from future FLTK versions. + + The class of an instance of an Fl_Device subclass can be checked with code such as: + \code + if ( instance->class_name() == Fl_Printer::class_id ) { ... } + \endcode + */ + virtual const char *class_name() {return class_id;}; + /** + Virtual destructor. + + The destructor of Fl_Device must be virtual to make the destructors of + derived classes being called correctly on destruction. + */ + virtual ~Fl_Device() {}; +}; + +#define FL_REGION_STACK_SIZE 10 +#define FL_MATRIX_STACK_SIZE 32 +/** + \brief A virtual class subclassed for each graphics driver FLTK uses. + Typically, FLTK applications do not use directly objects from this class. Rather, they perform + drawing operations (e.g., fl_rectf()) that operate on the current drawing surface (see Fl_Surface_Device). + Drawing operations are functionally presented in \ref drawing and as function lists + in the \ref fl_drawings and \ref fl_attributes modules. The \ref fl_graphics_driver global variable + gives at any time the graphics driver used by all drawing operations. Its value changes when + drawing operations are directed to another drawing surface by Fl_Surface_Device::set_current(). + + \p The Fl_Graphics_Driver class is of interest if one wants to perform new kinds of drawing operations. + An example would be to draw to a PDF file. This would involve creating a new Fl_Graphics_Driver derived + class. This new class should implement all virtual methods of the Fl_Graphics_Driver class + to support all FLTK drawing functions. + */ +class FL_EXPORT Fl_Graphics_Driver : public Fl_Device { + friend class Fl_Pixmap; + friend class Fl_Bitmap; + friend class Fl_RGB_Image; +public: + // The following functions create the various graphics drivers that are required + // for core operations. They must be implemented as members of Fl_Graphics_Driver, + // but located in the device driver module that is linked to the core library + static Fl_Graphics_Driver *newMainGraphicsDriver(); + //static Fl_Graphics_Driver *newOpenGLGraphicsDriver(); + //static Fl_Graphics_Driver *newPrinterGraphicsDriver(); + //static Fl_Graphics_Driver *new...; +public: + /** A 2D coordinate transformation matrix */ + struct matrix {double a, b, c, d, x, y;}; + /** Features that a derived class may possess. */ + typedef enum { + NATIVE = 1, /**< native graphics driver for the platform */ + PRINTER = 2 /**< graphics driver for a printer drawing surface */ + } driver_feature; + + int fl_clip_state_number; +protected: + static const matrix m0; + Fl_Font font_; // current font + Fl_Fontsize size_; // current font size + Fl_Color color_; // current color + int sptr; + static const int matrix_stack_size = FL_MATRIX_STACK_SIZE; + matrix stack[FL_MATRIX_STACK_SIZE]; + matrix m; + int n, p_size, gap_; + XPOINT *p; + int what; + int rstackptr; + static const int region_stack_max = FL_REGION_STACK_SIZE - 1; + Fl_Region rstack[FL_REGION_STACK_SIZE]; + Fl_Font_Descriptor *font_descriptor_; +#ifndef FL_DOXYGEN + enum {LINE, LOOP, POLYGON, POINT_}; + inline int vertex_no() { return n; } + inline XPOINT *vertices() {return p;} + inline int vertex_kind() {return what;} +#endif + matrix *fl_matrix; /**< Points to the current coordinate transformation matrix */ + + // === all code below in this class has been to the reorganisation FL_PORTING process +public: + static const char *class_id; + virtual const char *class_name() {return class_id;}; + Fl_Graphics_Driver(); + virtual ~Fl_Graphics_Driver() { if (p) free(p); } +public: + // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx + virtual void point(int x, int y) = 0; + virtual void rect(int x, int y, int w, int h) = 0; + virtual void focus_rect(int x, int y, int w, int h); + virtual void rectf(int x, int y, int w, int h) = 0; + virtual void line(int x, int y, int x1, int y1) = 0; + virtual void line(int x, int y, int x1, int y1, int x2, int y2) = 0; + virtual void xyline(int x, int y, int x1) = 0; + virtual void xyline(int x, int y, int x1, int y2) = 0; + virtual void xyline(int x, int y, int x1, int y2, int x3) = 0; + virtual void yxline(int x, int y, int y1) = 0; + virtual void yxline(int x, int y, int y1, int x2) = 0; + virtual void yxline(int x, int y, int y1, int x2, int y3) = 0; + virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) = 0; + virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; + virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) = 0; + virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; + // --- clipping + virtual void push_clip(int x, int y, int w, int h) = 0; + virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) = 0; + virtual int not_clipped(int x, int y, int w, int h) = 0; + virtual void push_no_clip() = 0; + virtual void pop_clip() = 0; + virtual Fl_Region clip_region(); // has default implementation + virtual void clip_region(Fl_Region r); // has default implementation + virtual void restore_clip(); + // --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx + virtual void push_matrix(); + virtual void pop_matrix(); + virtual void mult_matrix(double a, double b, double c, double d, double x, double y); + virtual void rotate(double d); + virtual void scale(double x, double y); + virtual void scale(double x); + virtual void translate(double x,double y); + virtual void begin_points(); + virtual void begin_line(); + virtual void begin_loop(); + virtual void begin_polygon(); + virtual void begin_complex_polygon() = 0; + virtual double transform_x(double x, double y); + virtual double transform_y(double x, double y); + virtual double transform_dx(double x, double y); + virtual double transform_dy(double x, double y); + virtual void transformed_vertex(double xf, double yf) = 0; + virtual void vertex(double x, double y) = 0; + virtual void end_points() = 0; + virtual void end_line() = 0; + virtual void end_loop() = 0; + virtual void end_polygon() = 0; + virtual void end_complex_polygon() = 0; + virtual void gap() = 0; + virtual void circle(double x, double y, double r) = 0; + // --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed + virtual void arc(double x, double y, double r, double start, double end); + // --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx + virtual void arc(int x, int y, int w, int h, double a1, double a2) = 0; + virtual void pie(int x, int y, int w, int h, double a1, double a2) = 0; + // --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed + virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3); + // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx + virtual void line_style(int style, int width=0, char* dashes=0) = 0; + // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx + virtual void color(Fl_Color c) { color_ = c; } + virtual Fl_Color color() { return color_; } + virtual void color(uchar r, uchar g, uchar b) = 0; + // --- implementation is in src/fl_font.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx + virtual void draw(const char *str, int n, int x, int y) = 0; + virtual void draw(const char *str, int n, float x, float y) { draw(str, n, (int)(x+0.5), (int)(y+0.5));} + virtual void draw(int angle, const char *str, int n, int x, int y) { draw(str, n, x, y); } + virtual void rtl_draw(const char *str, int n, int x, int y) { draw(str, n, x, y); } + /** Returns non-zero if the graphics driver possesses the \p feature */ + virtual int has_feature(driver_feature feature) { return 0; } + virtual void font(Fl_Font face, Fl_Fontsize fsize) {font_ = face; size_ = fsize;} + virtual Fl_Font font() {return font_; } + virtual Fl_Fontsize size() {return size_; } + virtual double width(const char *str, int n) { return 0; } + virtual double width(unsigned int c) { char ch = (char)c; return width(&ch, 1); } + virtual void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); + virtual int height() { return size(); } + virtual int descent() { return 0; } + virtual Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;} + virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;} + // --- implementation is in src/fl_image.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx + virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) = 0; + virtual fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array) { return 0; } + virtual fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array) { return 0; } + virtual void uncache(Fl_Bitmap *img, fl_uintptr_t &id_) { } + virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { } + virtual void delete_bitmask(Fl_Bitmask bm) = 0; + virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) {} + virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) {} + virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) {} + virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) {} + /** \brief Draws an Fl_RGB_Image object to the device. + * + Specifies a bounding box for the image, with the origin (upper left-hand corner) of + the image offset by the cx and cy arguments. + */ + virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) {} + /** \brief Draws an Fl_Pixmap object to the device. + * + Specifies a bounding box for the image, with the origin (upper left-hand corner) of + the image offset by the cx and cy arguments. + */ + virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) {} + /** \brief Draws an Fl_Bitmap object to the device. + * + Specifies a bounding box for the image, with the origin (upper left-hand corner) of + the image offset by the cx and cy arguments. + */ + virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {} + virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H); + virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); + +protected: + // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx + virtual void transformed_vertex0(COORD_T x, COORD_T y); + virtual void fixloop(); +}; + + + +#if defined(__APPLE__) + +#elif defined(WIN32) || defined(FL_DOXYGEN) + +#if FL_LIBRARY +#include "src/drivers/GDI/Fl_GDI_Graphics_Driver.h" +#endif + +#elif defined(FL_PORTING) + +# pragma message "FL_PORTING: define a native graphics driver Fl_xxx_Graphics_Driver" +class FL_EXPORT Fl_XXX_Graphics_Driver : public Fl_Graphics_Driver { +protected: + // --- recently moved implementations (see FL_PORTING efforts) + void point(int x, int y) { } + void rect(int x, int y, int w, int h) { } +}; + +#else // X11 + +#if FL_LIBRARY +#include "src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h" +#endif + +#endif + + + +/** + A drawing surface that's susceptible to receive graphical output. + Any FLTK application has at any time a current drawing surface to which all drawing requests are directed. + The current surface is given by Fl_Surface_Device::surface(). + When main() begins running, the current drawing surface has been set to the computer's display, + an instance of the Fl_Display_Device class. + + A drawing surface other than the computer's display, is typically used as follows: + <ol><li> Create \c surface, an object from a particular Fl_Surface_Device derived class (e.g., Fl_Copy_Surface, Fl_Printer). + <li> Memorize what is the current drawing surface with <tt> Fl_Surface_Device *old_current = Fl_Surface_Device::surface();</tt> + <li> Call \c surface->set_current(); to redirect all graphics requests to \c surface which becomes the new + current drawing surface (not necessary with class Fl_Printer because it is done by Fl_Printer::start_job()). + <li> At this point any of the \ref fl_drawings (e.g., fl_rect()) or the \ref fl_attributes or \ref drawing_images functions + (e.g., fl_draw_image(), Fl_Image::draw()) operates on the new current drawing surface. + Certain drawing surfaces allow additional ways to draw to them (e.g., Fl_Printer::print_widget(), Fl_Image_Surface::draw()). + <li> After all drawing requests have been performed, redirect graphics requests back to their previous destination + with \c old_current->set_current();. + <li> Delete \c surface. + </ol> + */ +class FL_EXPORT Fl_Surface_Device : public Fl_Device { + /** \brief The graphics driver in use by this surface. */ + Fl_Graphics_Driver *_driver; + static Fl_Surface_Device *_surface; // the surface that currently receives graphics output + static Fl_Surface_Device *default_surface(); // create surface is none exists yet +protected: + /** \brief Constructor that sets the graphics driver to use for the created surface. */ + Fl_Surface_Device(Fl_Graphics_Driver *graphics_driver) {_driver = graphics_driver; }; +public: + static const char *class_id; + const char *class_name() {return class_id;}; + virtual void set_current(void); + /** \brief Sets the graphics driver of this drawing surface. */ + inline void driver(Fl_Graphics_Driver *graphics_driver) {_driver = graphics_driver;}; + /** \brief Returns the graphics driver of this drawing surface. */ + inline Fl_Graphics_Driver *driver() {return _driver; }; + /** The current drawing surface. + In other words, the Fl_Surface_Device object that currently receives all graphics output */ + static inline Fl_Surface_Device *surface() { + return _surface ? _surface : default_surface(); + }; + /** \brief The destructor. */ + virtual ~Fl_Surface_Device() {} +}; + +/** + A display to which the computer can draw. + When the program begins running, an Fl_Display_Device instance has been created and made the current drawing surface. + There is no need to create any other object of this class. + */ +class FL_EXPORT Fl_Display_Device : public Fl_Surface_Device { + friend class Fl_X; + friend class Fl_Graphics_Driver; + static Fl_Display_Device *_display; // the platform display device + static bool high_res_window_; //< true when drawing to a window of a retina display (Mac OS X only) +public: + static const char *class_id; + const char *class_name() {return class_id;}; + Fl_Display_Device(Fl_Graphics_Driver *graphics_driver); + static Fl_Display_Device *display_device(); + static bool high_resolution() {return high_res_window_;} +}; + +/** + This plugin socket allows the integration of new device drivers for special + window or screen types. It is currently used to provide an automated printing + service and screen capture for OpenGL windows, if linked with fltk_gl. + */ +class FL_EXPORT Fl_Device_Plugin : public Fl_Plugin { +public: + /** \brief The constructor */ + Fl_Device_Plugin(const char *pluginName) + : Fl_Plugin(klass(), pluginName) { } + /** \brief Returns the class name */ + virtual const char *klass() { return "fltk:device"; } + /** \brief Returns the plugin name */ + virtual const char *name() = 0; + /** \brief Prints a widget + \param w the widget + \param x,y offsets where to print relatively to coordinates origin + \param height height of the current drawing area + */ + virtual int print(Fl_Widget* w, int x, int y, int height) = 0; + /** captures a rectangle of a widget as an image + \return The captured pixels as an RGB image + */ + virtual Fl_RGB_Image* rectangle_capture(Fl_Widget *widget, int x, int y, int w, int h) = 0; +}; + +#endif // Fl_Device_H + +// +// End of "$Id$". +// diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H new file mode 100644 index 000000000..e1c653c9d --- /dev/null +++ b/FL/Fl_Graphics_Driver.H @@ -0,0 +1,263 @@ +// +// "$Id$" +// +// Definition of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device +// for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/** \file Fl_Graphics_Driver.H + \brief declaration of classe Fl_Graphics_Driver. +*/ + +#ifndef FL_GRAPHICS_DRIVER_H +#define FL_GRAPHICS_DRIVER_H + +#include <FL/x.H> +#include <FL/Fl_DevIce.H> +#include <FL/Fl_Image.H> +#include <FL/Fl_Bitmap.H> +#include <FL/Fl_Pixmap.H> +#include <FL/Fl_RGB_Image.H> +#include <stdlib.h> + +class Fl_Graphics_Driver; +class Fl_Font_Descriptor; +/** \brief Points to the driver that currently receives all graphics requests */ +FL_EXPORT extern Fl_Graphics_Driver *fl_graphics_driver; + +/** + signature of image generation callback function. + \param[in] data user data passed to function + \param[in] x,y,w position and width of scan line in image + \param[out] buf buffer for generated image data. You must copy \p w + pixels from scanline \p y, starting at pixel \p x + to this buffer. + */ +typedef void (*Fl_Draw_Image_Cb)(void* data,int x,int y,int w,uchar* buf); + +// typedef what the x,y fields in a point are: +#ifdef WIN32 +typedef int COORD_T; +# define XPOINT XPoint +#elif defined(__APPLE__) +typedef float COORD_T; +typedef struct { float x; float y; } QPoint; +# define XPOINT QPoint +extern float fl_quartz_line_width_; +#elif defined(FL_PORTING) +# pragma message "FL_PORTING: define types for COORD_T and XPOINT" +typedef int COORD_T; // default if not ported +typedef struct { int x; int y; } QPoint; +# define XPOINT QPoint +#else +typedef short COORD_T; +# define XPOINT XPoint +#endif + + +#define FL_REGION_STACK_SIZE 10 +#define FL_MATRIX_STACK_SIZE 32 +/** + \brief A virtual class subclassed for each graphics driver FLTK uses. + Typically, FLTK applications do not use directly objects from this class. Rather, they perform + drawing operations (e.g., fl_rectf()) that operate on the current drawing surface (see Fl_Surface_Device). + Drawing operations are functionally presented in \ref drawing and as function lists + in the \ref fl_drawings and \ref fl_attributes modules. The \ref fl_graphics_driver global variable + gives at any time the graphics driver used by all drawing operations. Its value changes when + drawing operations are directed to another drawing surface by Fl_Surface_Device::set_current(). + + \p The Fl_Graphics_Driver class is of interest if one wants to perform new kinds of drawing operations. + An example would be to draw to a PDF file. This would involve creating a new Fl_Graphics_Driver derived + class. This new class should implement all virtual methods of the Fl_Graphics_Driver class + to support all FLTK drawing functions. + */ +class FL_EXPORT Fl_Graphics_Driver : public Fl_Device { + friend class Fl_Pixmap; + friend class Fl_Bitmap; + friend class Fl_RGB_Image; +public: + // The following functions create the various graphics drivers that are required + // for core operations. They must be implemented as members of Fl_Graphics_Driver, + // but located in the device driver module that is linked to the core library + static Fl_Graphics_Driver *newMainGraphicsDriver(); + //static Fl_Graphics_Driver *newOpenGLGraphicsDriver(); + //static Fl_Graphics_Driver *newPrinterGraphicsDriver(); + //static Fl_Graphics_Driver *new...; +public: + /** A 2D coordinate transformation matrix */ + struct matrix {double a, b, c, d, x, y;}; + /** Features that a derived class may possess. */ + typedef enum { + NATIVE = 1, /**< native graphics driver for the platform */ + PRINTER = 2 /**< graphics driver for a printer drawing surface */ + } driver_feature; + + int fl_clip_state_number; +protected: + static const matrix m0; + Fl_Font font_; // current font + Fl_Fontsize size_; // current font size + Fl_Color color_; // current color + int sptr; + static const int matrix_stack_size = FL_MATRIX_STACK_SIZE; + matrix stack[FL_MATRIX_STACK_SIZE]; + matrix m; + int n, p_size, gap_; + XPOINT *p; + int what; + int rstackptr; + static const int region_stack_max = FL_REGION_STACK_SIZE - 1; + Fl_Region rstack[FL_REGION_STACK_SIZE]; + Fl_Font_Descriptor *font_descriptor_; +#ifndef FL_DOXYGEN + enum {LINE, LOOP, POLYGON, POINT_}; + inline int vertex_no() { return n; } + inline XPOINT *vertices() {return p;} + inline int vertex_kind() {return what;} +#endif + matrix *fl_matrix; /**< Points to the current coordinate transformation matrix */ + + // === all code below in this class has been to the reorganisation FL_PORTING process +public: + static const char *class_id; + virtual const char *class_name() {return class_id;}; + Fl_Graphics_Driver(); + virtual ~Fl_Graphics_Driver() { if (p) free(p); } +public: + // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx + virtual void point(int x, int y) = 0; + virtual void rect(int x, int y, int w, int h) = 0; + virtual void focus_rect(int x, int y, int w, int h); + virtual void rectf(int x, int y, int w, int h) = 0; + virtual void line(int x, int y, int x1, int y1) = 0; + virtual void line(int x, int y, int x1, int y1, int x2, int y2) = 0; + virtual void xyline(int x, int y, int x1) = 0; + virtual void xyline(int x, int y, int x1, int y2) = 0; + virtual void xyline(int x, int y, int x1, int y2, int x3) = 0; + virtual void yxline(int x, int y, int y1) = 0; + virtual void yxline(int x, int y, int y1, int x2) = 0; + virtual void yxline(int x, int y, int y1, int x2, int y3) = 0; + virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) = 0; + virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; + virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) = 0; + virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; + // --- clipping + virtual void push_clip(int x, int y, int w, int h) = 0; + virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) = 0; + virtual int not_clipped(int x, int y, int w, int h) = 0; + virtual void push_no_clip() = 0; + virtual void pop_clip() = 0; + virtual Fl_Region clip_region(); // has default implementation + virtual void clip_region(Fl_Region r); // has default implementation + virtual void restore_clip(); + // --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx + virtual void push_matrix(); + virtual void pop_matrix(); + virtual void mult_matrix(double a, double b, double c, double d, double x, double y); + virtual void rotate(double d); + virtual void scale(double x, double y); + virtual void scale(double x); + virtual void translate(double x,double y); + virtual void begin_points(); + virtual void begin_line(); + virtual void begin_loop(); + virtual void begin_polygon(); + virtual void begin_complex_polygon() = 0; + virtual double transform_x(double x, double y); + virtual double transform_y(double x, double y); + virtual double transform_dx(double x, double y); + virtual double transform_dy(double x, double y); + virtual void transformed_vertex(double xf, double yf) = 0; + virtual void vertex(double x, double y) = 0; + virtual void end_points() = 0; + virtual void end_line() = 0; + virtual void end_loop() = 0; + virtual void end_polygon() = 0; + virtual void end_complex_polygon() = 0; + virtual void gap() = 0; + virtual void circle(double x, double y, double r) = 0; + // --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed + virtual void arc(double x, double y, double r, double start, double end); + // --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx + virtual void arc(int x, int y, int w, int h, double a1, double a2) = 0; + virtual void pie(int x, int y, int w, int h, double a1, double a2) = 0; + // --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed + virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3); + // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx + virtual void line_style(int style, int width=0, char* dashes=0) = 0; + // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx + virtual void color(Fl_Color c) { color_ = c; } + virtual Fl_Color color() { return color_; } + virtual void color(uchar r, uchar g, uchar b) = 0; + // --- implementation is in src/fl_font.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx + virtual void draw(const char *str, int n, int x, int y) = 0; + virtual void draw(const char *str, int n, float x, float y) { draw(str, n, (int)(x+0.5), (int)(y+0.5));} + virtual void draw(int angle, const char *str, int n, int x, int y) { draw(str, n, x, y); } + virtual void rtl_draw(const char *str, int n, int x, int y) { draw(str, n, x, y); } + /** Returns non-zero if the graphics driver possesses the \p feature */ + virtual int has_feature(driver_feature feature) { return 0; } + virtual void font(Fl_Font face, Fl_Fontsize fsize) {font_ = face; size_ = fsize;} + virtual Fl_Font font() {return font_; } + virtual Fl_Fontsize size() {return size_; } + virtual double width(const char *str, int n) { return 0; } + virtual double width(unsigned int c) { char ch = (char)c; return width(&ch, 1); } + virtual void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); + virtual int height() { return size(); } + virtual int descent() { return 0; } + virtual Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;} + virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;} + // --- implementation is in src/fl_image.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx + virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) = 0; + virtual fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array) { return 0; } + virtual fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array) { return 0; } + virtual void uncache(Fl_Bitmap *img, fl_uintptr_t &id_) { } + virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { } + virtual void delete_bitmask(Fl_Bitmask bm) = 0; + virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) {} + virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) {} + virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) {} + virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) {} + /** \brief Draws an Fl_RGB_Image object to the device. + * + Specifies a bounding box for the image, with the origin (upper left-hand corner) of + the image offset by the cx and cy arguments. + */ + virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) {} + /** \brief Draws an Fl_Pixmap object to the device. + * + Specifies a bounding box for the image, with the origin (upper left-hand corner) of + the image offset by the cx and cy arguments. + */ + virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) {} + /** \brief Draws an Fl_Bitmap object to the device. + * + Specifies a bounding box for the image, with the origin (upper left-hand corner) of + the image offset by the cx and cy arguments. + */ + virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {} + virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H); + virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); + +protected: + // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx + virtual void transformed_vertex0(COORD_T x, COORD_T y); + virtual void fixloop(); +}; + +#endif // FL_GRAPHICS_DRIVER_H + +// +// End of "$Id$". +// diff --git a/FL/Fl_Image.H b/FL/Fl_Image.H index 6c44c94aa..5dad09c01 100644 --- a/FL/Fl_Image.H +++ b/FL/Fl_Image.H @@ -20,10 +20,11 @@ Fl_Image, Fl_RGB_Image classes. */ #ifndef Fl_Image_H -# define Fl_Image_H +#define Fl_Image_H -# include "Enumerations.H" +#include "Enumerations.H" #include <stdlib.h> +#include "Fl_Widget.H" // for fl_uintptr_t class Fl_Widget; class Fl_Pixmap; @@ -203,19 +204,10 @@ public: const uchar *array; int alloc_array; // Non-zero if array was allocated - private: - -#if defined(__APPLE__) || defined(WIN32) - void *id_; // for internal use - void *mask_; // for internal use (mask bitmap) -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define variables to hold an RGB image and a mask for Fl_RGB_Image" - unsigned id_; // don't use - unsigned mask_; // don't use -#else - unsigned id_; // for internal use - unsigned mask_; // for internal use (mask bitmap) -#endif // __APPLE__ || WIN32 +private: + // These two variables are used to cache the image and mask for the main display graphics driver + fl_uintptr_t id_; + fl_uintptr_t mask_; public: diff --git a/FL/Fl_Pixmap.H b/FL/Fl_Pixmap.H index 65f056b84..12e917978 100644 --- a/FL/Fl_Pixmap.H +++ b/FL/Fl_Pixmap.H @@ -49,33 +49,20 @@ class FL_EXPORT Fl_Pixmap : public Fl_Image { int prepare(int XP, int YP, int WP, int HP, int &cx, int &cy, int &X, int &Y, int &W, int &H); - protected: +protected: void measure(); - public: +public: int alloc_data; // Non-zero if data was allocated - private: +private: + // for internal use + fl_uintptr_t id_; + fl_uintptr_t mask_; -#if defined(WIN32) - UINT pixmap_bg_color; // RGB color used for pixmap background - void *id_; // for internal use - void *mask_; // for internal use (mask bitmap) -#elif defined(__APPLE__) - void *id_; // for internal use - void *mask_; // for internal use (mask bitmap) -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define member variables to store an RGB image and a mask for Fl_Pixmap" - void *id_; // don't use - void *mask_; // don't use -#else - unsigned id_; // for internal use - unsigned mask_; // for internal use (mask bitmap) -#endif // __APPLE__ || WIN32 - - public: +public: /** The constructors create a new pixmap from the specified XPM data. */ explicit Fl_Pixmap(char * const * D) : Fl_Image(-1,0,1), alloc_data(0), id_(0), mask_(0) {set_data((const char*const*)D); measure();} diff --git a/FL/fl_draw.H b/FL/fl_draw.H index 690534982..f108ce420 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -27,7 +27,7 @@ #include <FL/x.H> // for Fl_Region #include <FL/Enumerations.H> // for the color names #include <FL/Fl_Window.H> // for fl_set_spot() -#include <FL/Fl_Device.H> // for fl_graphics_driver +#include <FL/Fl_Graphics_Driver.H> // for fl_graphics_driver // Image class... class Fl_Image; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ad0572e3c..6157a3a62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ set(CPPFILES Fl_File_Chooser2.cxx Fl_File_Icon.cxx Fl_File_Input.cxx + Fl_Graphics_Driver.cxx Fl_Group.cxx Fl_Help_View.cxx Fl_Image.cxx @@ -211,6 +212,8 @@ else () endif (USE_X11) +source_group("Driver Source Files" FILES ${DRIVER_FILES}) + set(CPPFILES ${CPPFILES} ${DRIVER_FILES} @@ -238,6 +241,9 @@ set(GLCPPFILES gl_start.cxx glut_compatability.cxx glut_font.cxx +) + +set (GL_DRIVER_FILES drivers/OpenGL/Fl_OpenGL_Display_Device.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.cxx @@ -249,6 +255,13 @@ set(GLCPPFILES drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx ) +source_group("Driver Source Files" FILES ${GL_DRIVER_FILES}) + +set(GLCPPFILES + ${GLCPPFILES} + ${GL_DRIVER_FILES} +) + set(IMGCPPFILES fl_images_core.cxx Fl_BMP_Image.cxx diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx index 4d3627515..b5fa32c2c 100644 --- a/src/Fl_Bitmap.cxx +++ b/src/Fl_Bitmap.cxx @@ -23,14 +23,11 @@ The constructors create a new bitmap from the specified bitmap data.*/ #include <FL/Fl.H> -#include <FL/x.H> -#include "config_lib.h" #include <FL/fl_draw.H> #include <FL/Fl_Widget.H> #include <FL/Fl_Menu_Item.H> #include <FL/Fl_Bitmap.H> #include <FL/Fl_Printer.H> -#include "flstring.h" Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array) { return fl_graphics_driver->create_bitmask(w, h, array); @@ -117,38 +114,7 @@ void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy); } -#if defined(WIN32) -// TODO: move this code into the GDI driver in a sensible way -// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing... -static Fl_Bitmask 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; - Fl_Bitmask 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; -} -#endif - -int Fl_Bitmap::start(int XP, int YP, int WP, int HP, int &cx, int &cy, +int Fl_Bitmap::start(int XP, int YP, int WP, int HP, int &cx, int &cy, int &X, int &Y, int &W, int &H) { if (!array) { @@ -165,13 +131,8 @@ int Fl_Bitmap::start(int XP, int YP, int WP, int HP, int &cx, int &cy, if (cy < 0) {H += cy; Y -= cy; cy = 0;} if (cy+H > h()) H = h()-cy; if (H <= 0) return 1; -#if defined(WIN32) - if (!id_) id_ = fl_create_bitmap(w(), h(), array); -#elif defined(__APPLE__) || defined(USE_X11) - if (!id_) id_ = fl_create_bitmask(w(), h(), array); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: call the right function to create a bitmap" -#endif + if (!id_) + id_ = fl_graphics_driver->cache(this, w(), h(), array); return 0; } @@ -186,13 +147,7 @@ Fl_Bitmap::~Fl_Bitmap() { void Fl_Bitmap::uncache() { if (id_) { -#ifdef __APPLE_QUARTZ__ - fl_delete_bitmask((Fl_Bitmask)id_); -#elif defined(WIN32) || defined(USE_X11) - fl_delete_bitmask((Fl_Offscreen)id_); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: call the right function to create a bitmask" -#endif + fl_graphics_driver->uncache(this, id_); id_ = 0; } } diff --git a/src/Fl_Device.cxx b/src/Fl_Device.cxx index efbd0712d..bfb60d789 100644 --- a/src/Fl_Device.cxx +++ b/src/Fl_Device.cxx @@ -19,13 +19,39 @@ #include <FL/Fl.H> #include "config_lib.h" #include <FL/Fl_Device.H> -#include <FL/Fl_Image.H> -#include <FL/fl_draw.H> +#include <FL/Fl_Graphics_Driver.H> + +/* Attempt at an inheritance diagram. + + Fl_Device: base class for the core device systems + | + +- Fl_Surface_Device: any kind of surface that we can draw onto -> uses an Fl_Graphics_Driver + | + +- Fl_Display_Device: some kind of video device + +- Fl_Copy_Surface: create an image for dnd or copy/paste + +- Fl_Image_Surface: create an RGB Image + +- Fl_Paged_Device: output to a printer or similar + | + +- Fl_..._Surface_: platform specific driver + +- Fl_Printer: user can instantiate this to gain access to a printer + +- Fl_System_Printer: + +- Fl_PostScript_File_Device + | + +- Fl_PostScript_Printer + | + +- Fl_Graphics_Driver + | + +- Fl_..._Graphics_Driver: platform specific graphics driver + +TODO: + Window Device to handle creation of surfaces and manage events + System Device to handle file system acces, standard dialogs, etc. + +*/ const char *Fl_Device::class_id = "Fl_Device"; const char *Fl_Surface_Device::class_id = "Fl_Surface_Device"; const char *Fl_Display_Device::class_id = "Fl_Display_Device"; -const char *Fl_Graphics_Driver::class_id = "Fl_Graphics_Driver"; bool Fl_Display_Device::high_res_window_ = false; @@ -38,38 +64,8 @@ void Fl_Surface_Device::set_current(void) _surface = this; } -FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current target device of graphics operations Fl_Surface_Device* Fl_Surface_Device::_surface; // the current target surface of graphics operations -const Fl_Graphics_Driver::matrix Fl_Graphics_Driver::m0 = {1, 0, 0, 1, 0, 0}; - -Fl_Graphics_Driver::Fl_Graphics_Driver() { - font_ = 0; - size_ = 0; - sptr=0; rstackptr=0; - rstack[0] = NULL; - fl_clip_state_number=0; - m = m0; - fl_matrix = &m; - p = (XPOINT *)0; - font_descriptor_ = NULL; - p_size = 0; -}; - -void Fl_Graphics_Driver::text_extents(const char*t, int n, int& dx, int& dy, int& w, int& h) -{ - w = (int)width(t, n); - h = - height(); - dx = 0; - dy = descent(); -} - -void Fl_Graphics_Driver::focus_rect(int x, int y, int w, int h) -{ - line_style(FL_DOT); - rect(x, y, w, h); - line_style(FL_SOLID); -} /** A constructor that sets the graphics driver used by the display */ Fl_Display_Device::Fl_Display_Device(Fl_Graphics_Driver *graphics_driver) : Fl_Surface_Device(graphics_driver) { @@ -92,6 +88,7 @@ Fl_Surface_Device *Fl_Surface_Device::default_surface() Fl_Display_Device *Fl_Display_Device::_display = Fl_Display_Device::display_device(); + // // End of "$Id$". // diff --git a/src/Fl_Graphics_Device.cxx b/src/Fl_Graphics_Device.cxx new file mode 100644 index 000000000..22e17fa3a --- /dev/null +++ b/src/Fl_Graphics_Device.cxx @@ -0,0 +1,106 @@ +// +// "$Id$" +// +// implementation of Fl_Device class for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010-2012 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include "config_lib.h" +#include <FL/Fl_Device.H> +#include <FL/Fl_Image.H> +#include <FL/fl_draw.H> + +const char *Fl_Device::class_id = "Fl_Device"; +const char *Fl_Surface_Device::class_id = "Fl_Surface_Device"; +const char *Fl_Display_Device::class_id = "Fl_Display_Device"; +const char *Fl_Graphics_Driver::class_id = "Fl_Graphics_Driver"; + +bool Fl_Display_Device::high_res_window_ = false; + + +/** \brief Make this surface the current drawing surface. + This surface will receive all future graphics requests. */ +void Fl_Surface_Device::set_current(void) +{ + fl_graphics_driver = _driver; + _surface = this; +} + +FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current target device of graphics operations +Fl_Surface_Device* Fl_Surface_Device::_surface; // the current target surface of graphics operations + +const Fl_Graphics_Driver::matrix Fl_Graphics_Driver::m0 = {1, 0, 0, 1, 0, 0}; + +Fl_Graphics_Driver::Fl_Graphics_Driver() { + font_ = 0; + size_ = 0; + sptr=0; rstackptr=0; + rstack[0] = NULL; + fl_clip_state_number=0; + m = m0; + fl_matrix = &m; + p = (XPOINT *)0; + font_descriptor_ = NULL; + p_size = 0; +}; + +void Fl_Graphics_Driver::text_extents(const char*t, int n, int& dx, int& dy, int& w, int& h) +{ + w = (int)width(t, n); + h = - height(); + dx = 0; + dy = descent(); +} + +void Fl_Graphics_Driver::focus_rect(int x, int y, int w, int h) +{ + line_style(FL_DOT); + rect(x, y, w, h); + line_style(FL_SOLID); +} + +/** A constructor that sets the graphics driver used by the display */ +Fl_Display_Device::Fl_Display_Device(Fl_Graphics_Driver *graphics_driver) : Fl_Surface_Device(graphics_driver) { + this->set_current(); +}; + + +/** Returns the platform display device. */ +Fl_Display_Device *Fl_Display_Device::display_device() { + static Fl_Display_Device *display = new Fl_Display_Device(Fl_Graphics_Driver::newMainGraphicsDriver()); + return display; +}; + + +Fl_Surface_Device *Fl_Surface_Device::default_surface() +{ + return Fl_Display_Device::display_device(); +} + + +Fl_Display_Device *Fl_Display_Device::_display = Fl_Display_Device::display_device(); + + +/** Draws an Fl_Image scaled to width \p W & height \p H with top-left corner at \em X,Y + \return zero when the graphics driver doesn't implement scaled drawing, non-zero if it does implement it. + */ +int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) { + return 0; +} + + +// +// End of "$Id$". +// diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx new file mode 100644 index 000000000..365f1df5e --- /dev/null +++ b/src/Fl_Graphics_Driver.cxx @@ -0,0 +1,69 @@ +// +// "$Id$" +// +// implementation of Fl_Device class for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010-2012 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include "config_lib.h" +#include <FL/Fl_Graphics_Driver.H> +#include <FL/Fl_Image.H> +#include <FL/fl_draw.H> + +const char *Fl_Graphics_Driver::class_id = "Fl_Graphics_Driver"; + +FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current target device of graphics operations + +const Fl_Graphics_Driver::matrix Fl_Graphics_Driver::m0 = {1, 0, 0, 1, 0, 0}; + +Fl_Graphics_Driver::Fl_Graphics_Driver() { + font_ = 0; + size_ = 0; + sptr=0; rstackptr=0; + rstack[0] = NULL; + fl_clip_state_number=0; + m = m0; + fl_matrix = &m; + p = (XPOINT *)0; + font_descriptor_ = NULL; + p_size = 0; +}; + +void Fl_Graphics_Driver::text_extents(const char*t, int n, int& dx, int& dy, int& w, int& h) +{ + w = (int)width(t, n); + h = - height(); + dx = 0; + dy = descent(); +} + +void Fl_Graphics_Driver::focus_rect(int x, int y, int w, int h) +{ + line_style(FL_DOT); + rect(x, y, w, h); + line_style(FL_SOLID); +} + +/** Draws an Fl_Image scaled to width \p W & height \p H with top-left corner at \em X,Y + \return zero when the graphics driver doesn't implement scaled drawing, non-zero if it does implement it. + */ +int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) { + return 0; +} + + +// +// End of "$Id$". +// diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index 907035893..35871765c 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -32,10 +32,6 @@ #else #endif -#ifdef WIN32 -void fl_release_dc(HWND, HDC); // from Fl_win32.cxx -#endif - void fl_restore_clip(); // from fl_rect.cxx // @@ -75,25 +71,6 @@ void Fl_Image::draw(int XP, int YP, int, int, int, int) { } -#if defined(WIN32) || defined (USE_X11) -static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, - int &X, int &Y, int &W, int &H) -{ - // account for current clip region (faster on Irix): - fl_clip_box(XP,YP,WP,HP,X,Y,W,H); - cx += X-XP; cy += Y-YP; - // clip the box down to the size of image, quit if empty: - if (cx < 0) {W += cx; X -= cx; cx = 0;} - if (cx+W > w) W = w-cx; - if (W <= 0) return 1; - if (cy < 0) {H += cy; Y -= cy; cy = 0;} - if (cy+H > h) H = h-cy; - if (H <= 0) return 1; - return 0; -} -#endif // defined(WIN32) || defined (USE_X11) - - /** The protected method draw_empty() draws a box with an X in it. It can be used to draw any image that lacks image @@ -313,34 +290,12 @@ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg): the image. */ Fl_RGB_Image::~Fl_RGB_Image() { -#ifdef __APPLE__ - if (id_) CGImageRelease((CGImageRef)id_); - else if (alloc_array) delete[] (uchar *)array; -#else uncache(); if (alloc_array) delete[] (uchar *)array; -#endif } void Fl_RGB_Image::uncache() { -#ifdef __APPLE__ - if (id_) { - if (mask_) *(bool*)mask_ = false; - CGImageRelease((CGImageRef)id_); - id_ = 0; - mask_ = NULL; - } -#else - if (id_) { - fl_delete_offscreen((Fl_Offscreen)id_); - id_ = 0; - } - - if (mask_) { - fl_delete_bitmask((Fl_Bitmask)mask_); - mask_ = 0; - } -#endif + fl_graphics_driver->uncache(this, id_, mask_); } Fl_Image *Fl_RGB_Image::copy(int W, int H) { @@ -587,199 +542,10 @@ void Fl_RGB_Image::desaturate() { d(new_d); } -#if !defined(WIN32) && !defined(__APPLE__) -// Composite an image with alpha on systems that don't have accelerated -// alpha compositing... -static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { - int ld = img->ld(); - if (ld == 0) ld = img->w() * img->d(); - uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d(); - int srcskip = ld - img->d() * W; - - uchar *dst = new uchar[W * H * 3]; - uchar *dstptr = dst; - - fl_read_image(dst, X, Y, W, H, 0); - - uchar srcr, srcg, srcb, srca; - uchar dstr, dstg, dstb, dsta; - - if (img->d() == 2) { - // Composite grayscale + alpha over RGB... - for (int y = H; y > 0; y--, srcptr+=srcskip) - for (int x = W; x > 0; x--) { - srcg = *srcptr++; - srca = *srcptr++; - - dstr = dstptr[0]; - dstg = dstptr[1]; - dstb = dstptr[2]; - dsta = 255 - srca; - - *dstptr++ = (srcg * srca + dstr * dsta) >> 8; - *dstptr++ = (srcg * srca + dstg * dsta) >> 8; - *dstptr++ = (srcg * srca + dstb * dsta) >> 8; - } - } else { - // Composite RGBA over RGB... - for (int y = H; y > 0; y--, srcptr+=srcskip) - for (int x = W; x > 0; x--) { - srcr = *srcptr++; - srcg = *srcptr++; - srcb = *srcptr++; - srca = *srcptr++; - - dstr = dstptr[0]; - dstg = dstptr[1]; - dstb = dstptr[2]; - dsta = 255 - srca; - - *dstptr++ = (srcr * srca + dstr * dsta) >> 8; - *dstptr++ = (srcg * srca + dstg * dsta) >> 8; - *dstptr++ = (srcb * srca + dstb * dsta) >> 8; - } - } - - fl_draw_image(dst, X, Y, W, H, 3, 0); - - delete[] dst; -} -#endif // !WIN32 && !__APPLE__ - void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy); } -/** Draws an Fl_Image scaled to width \p W & height \p H with top-left corner at \em X,Y - \return zero when the graphics driver doesn't implement scaled drawing, non-zero if it does implement it. - */ -int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) { - return 0; -} - -#ifdef __APPLE__ - -#elif defined(WIN32) -static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask) -{ - Fl_Offscreen offs = fl_create_offscreen(img->w(), img->h()); - if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { - fl_begin_offscreen(offs); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); - fl_end_offscreen(); - } else { - fl_begin_offscreen(offs); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); - fl_end_offscreen(); - if (img->d() == 2 || img->d() == 4) { - *pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array); - } - } - return offs; -} - -void Fl_GDI_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - // Don't draw an empty image... - if (!img->d() || !img->array) { - img->draw_empty(XP, YP); - return; - } - if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) { - return; - } - if (!img->id_) img->id_ = build_id(img, &(img->mask_)); - if (img->mask_) { - HDC new_gc = CreateCompatibleDC(fl_gc); - int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)img->mask_); - BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); - SelectObject(new_gc, (void*)img->id_); - BitBlt(fl_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, (Fl_Offscreen)img->id_, cx, cy); - } else { - copy_offscreen(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy); - } -} - -int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { - XFORM old_tr, tr; - GetWorldTransform(fl_gc, &old_tr); // storing old transform - tr.eM11 = float(WP)/float(img->w()); - tr.eM22 = float(HP)/float(img->h()); - tr.eM12 = tr.eM21 = 0; - tr.eDx = XP; - tr.eDy = YP; - ModifyWorldTransform(fl_gc, &tr, MWT_LEFTMULTIPLY); - img->draw(0, 0, img->w(), img->h(), 0, 0); - SetWorldTransform(fl_gc, &old_tr); - return 1; -} - -#elif defined(FL_PORTING) - -# pragma message "FL_PORTING: implement RGB image handling here" - -#else -void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - // Don't draw an empty image... - if (!img->d() || !img->array) { - img->draw_empty(XP, YP); - return; - } - if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) { - return; - } - if (!img->id_) { - if (img->d() == 1 || img->d() == 3) { - img->id_ = fl_create_offscreen(img->w(), img->h()); - fl_begin_offscreen((Fl_Offscreen)img->id_); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); - fl_end_offscreen(); - } else if (img->d() == 4 && fl_can_do_alpha_blending()) { - img->id_ = fl_create_offscreen_with_alpha(img->w(), img->h()); - fl_begin_offscreen((Fl_Offscreen)img->id_); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d() | FL_IMAGE_WITH_ALPHA, - img->ld()); - fl_end_offscreen(); - } - } - if (img->id_) { - if (img->mask_) { - // I can't figure out how to combine a mask with existing region, - // so cut the image down to a clipped rectangle: - int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H); - cx += nx-X; X = nx; - cy += ny-Y; Y = ny; - // make X use the bitmap as a mask: - XSetClipMask(fl_display, fl_gc, img->mask_); - int ox = X-cx; if (ox < 0) ox += img->w(); - int oy = Y-cy; if (oy < 0) oy += img->h(); - XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); - } - - if (img->d() == 4 && fl_can_do_alpha_blending()) - copy_offscreen_with_alpha(X, Y, W, H, img->id_, cx, cy); - else - copy_offscreen(X, Y, W, H, img->id_, cx, cy); - - if (img->mask_) { - // put the old clip region back - XSetClipOrigin(fl_display, fl_gc, 0, 0); - fl_restore_clip(); - } - } else { - // Composite image with alpha manually each time... - alpha_blend(img, X, Y, W, H, cx, cy); - } -} - -#endif - void Fl_RGB_Image::label(Fl_Widget* widget) { widget->image(this); } diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx index 01a3afa6e..56512994e 100644 --- a/src/Fl_Pixmap.cxx +++ b/src/Fl_Pixmap.cxx @@ -23,7 +23,6 @@ // Implemented without using the xpm library (which I can't use because // it interferes with the color cube used by fl_draw_image). -#include "config_lib.h" #include <FL/Fl.H> #include <FL/fl_draw.H> #include <FL/x.H> @@ -32,38 +31,10 @@ #include <FL/Fl_Pixmap.H> #include <FL/Fl_Printer.H> -#if defined(WIN32) -#elif defined(__APPLE__) -#include "src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h" -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: this file needs a lot of custom code to draw Pixmaps correctly" -#else -#endif - -#if defined(USE_X11) -# if HAVE_X11_XREGION_H -# include <X11/Xregion.h> -# else // if the X11/Xregion.h header is not available, we assume this is the layout of an X11 Region: -typedef struct { - short x1, x2, y1, y2; -} BOX; -struct _XRegion { - long size; - long numRects; - BOX *rects; - BOX extents; -}; -# endif // HAVE_X11_XREGION_H -#endif // USE_X11 - #include <stdio.h> #include "flstring.h" #include <ctype.h> -#ifdef WIN32 -extern void fl_release_dc(HWND, HDC); // located in Fl_win32.cxx -#endif - extern uchar **fl_mask_bitmap; // used by fl_draw_pixmap.cxx to store mask void fl_restore_clip(); // in fl_rect.cxx @@ -117,132 +88,11 @@ int Fl_Pixmap::prepare(int XP, int YP, int WP, int HP, int &cx, int &cy, return 1; } if (!id_) { -#ifdef __APPLE__ - id_ = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w(), h()); -#else - id_ = fl_create_offscreen(w(), h()); -#endif - fl_begin_offscreen((Fl_Offscreen)id_); -#ifndef __APPLE__ - uchar *bitmap = 0; - fl_mask_bitmap = &bitmap; -#endif - fl_draw_pixmap(data(), 0, 0, FL_BLACK); -#ifndef __APPLE__ -#if defined(WIN32) - extern UINT win_pixmap_bg_color; // computed by fl_draw_pixmap() - this->pixmap_bg_color = win_pixmap_bg_color; -#endif - fl_mask_bitmap = 0; - if (bitmap) { - mask_ = fl_create_bitmask(w(), h(), bitmap); - delete[] bitmap; - } -#endif - fl_end_offscreen(); + id_ = fl_graphics_driver->cache(this, w(), h(), data()); } return 0; } -//------------------------------------------------------------------------------ -#ifdef __APPLE__ // Apple, Mac OS X -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -#elif defined(WIN32) // Windows GDI -//------------------------------------------------------------------------------ - -void Fl_GDI_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; - if (pxm->mask_) { - HDC new_gc = CreateCompatibleDC(fl_gc); - int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)pxm->mask_); - BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); - SelectObject(new_gc, (void*)pxm->id_); - BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT); - RestoreDC(new_gc,save); - DeleteDC(new_gc); - } else { - copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); - } -} - - -void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; - typedef BOOL (WINAPI* fl_transp_func) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); - static HMODULE hMod = NULL; - static fl_transp_func fl_TransparentBlt = NULL; - if (!hMod) { - hMod = LoadLibrary("MSIMG32.DLL"); - if(hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt"); - } - if (fl_TransparentBlt) { - HDC new_gc = CreateCompatibleDC(fl_gc); - int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)pxm->id_); - // print all of offscreen but its parts in background color - fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, W, H, pxm->pixmap_bg_color ); - RestoreDC(new_gc,save); - DeleteDC(new_gc); - } - else { - copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); - } -} - -//------------------------------------------------------------------------------ -#elif defined(FL_PORTING) -#pragma message "Implement Fl_XXX_Graphics_Driver methods here" -//------------------------------------------------------------------------------ -#else // X11, Xlib -//------------------------------------------------------------------------------ - -void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; - if (pxm->mask_) { - // make X use the bitmap as a mask: - XSetClipMask(fl_display, fl_gc, pxm->mask_); - XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); - if (clip_region()) { - // At this point, XYWH is the bounding box of the intersection between - // the current clip region and the (portion of the) pixmap we have to draw. - // The current clip region is often a rectangle. But, when a window with rounded - // corners is moved above another window, expose events may create a complex clip - // region made of several (e.g., 10) rectangles. We have to draw only in the clip - // region, and also to mask out the transparent pixels of the image. This can't - // be done in a single Xlib call for a multi-rectangle clip region. Thus, we - // process each rectangle of the intersection between the clip region and XYWH. - // See also STR #3206. - Region r = XRectangleRegion(X,Y,W,H); - XIntersectRegion(r, clip_region(), r); - int X1, Y1, W1, H1; - for (int i = 0; i < r->numRects; i++) { - X1 = r->rects[i].x1; - Y1 = r->rects[i].y1; - W1 = r->rects[i].x2 - r->rects[i].x1; - H1 = r->rects[i].y2 - r->rects[i].y1; - copy_offscreen(X1, Y1, W1, H1, pxm->id_, cx + (X1 - X), cy + (Y1 - Y)); - } - XDestroyRegion(r); - } else { - copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); - } - // put the old clip region back - XSetClipOrigin(fl_display, fl_gc, 0, 0); - restore_clip(); - } - else copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); -} - -//------------------------------------------------------------------------------ -#endif // (platform-specific) -//------------------------------------------------------------------------------ - /** The destructor frees all memory and server resources that are used by the pixmap. diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h index 06e040f1a..1dd62a4e6 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h @@ -25,7 +25,7 @@ #ifndef FL_GDI_GRAPHICS_DRIVER_H #define FL_GDI_GRAPHICS_DRIVER_H -#include <FL/Fl_Device.H> +#include <FL/Fl_Graphics_Driver.H> /** @@ -56,6 +56,10 @@ public: void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); + fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + void uncache(Fl_Bitmap *img, fl_uintptr_t &id_); + void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); double width(const char *str, int n); double width(unsigned int c); void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx index a6d32d6e4..f12de853b 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx @@ -43,6 +43,8 @@ #define MAXBUFFER 0x40000 // 256k +void fl_release_dc(HWND, HDC); // from Fl_win32.cxx + #if USE_COLORMAP // error-diffusion dither into the FLTK colormap @@ -459,6 +461,192 @@ void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, } +static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask) +{ + Fl_Offscreen offs = fl_create_offscreen(img->w(), img->h()); + if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { + fl_begin_offscreen(offs); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); + fl_end_offscreen(); + } else { + fl_begin_offscreen(offs); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); + fl_end_offscreen(); + if (img->d() == 2 || img->d() == 4) { + *pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array); + } + } + return offs; +} + + +static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, + int &X, int &Y, int &W, int &H) +{ + // account for current clip region (faster on Irix): + fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if (cx+W > w) W = w-cx; + if (W <= 0) return 1; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if (cy+H > h) H = h-cy; + if (H <= 0) return 1; + return 0; +} + + +void Fl_GDI_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + // Don't draw an empty image... + if (!img->d() || !img->array) { + img->draw_empty(XP, YP); + return; + } + if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!img->id_) img->id_ = build_id(img, &(img->mask_)); + if (img->mask_) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)img->mask_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); + SelectObject(new_gc, (void*)img->id_); + BitBlt(fl_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, (Fl_Offscreen)img->id_, cx, cy); + } else { + copy_offscreen(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy); + } +} + +int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { + XFORM old_tr, tr; + GetWorldTransform(fl_gc, &old_tr); // storing old transform + tr.eM11 = float(WP)/float(img->w()); + tr.eM22 = float(HP)/float(img->h()); + tr.eM12 = tr.eM21 = 0; + tr.eDx = XP; + tr.eDy = YP; + ModifyWorldTransform(fl_gc, &tr, MWT_LEFTMULTIPLY); + img->draw(0, 0, img->w(), img->h(), 0, 0); + SetWorldTransform(fl_gc, &old_tr); + return 1; +} + +void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) +{ + if (id_) { + fl_delete_offscreen((Fl_Offscreen)id_); + id_ = 0; + } + + if (mask_) { + fl_delete_bitmask((Fl_Bitmask)mask_); + mask_ = 0; + } +} + +// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing... +static Fl_Bitmask 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; + Fl_Bitmask 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; +} + +fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { + return (fl_uintptr_t)create_bitmap(w, h, array); +} + +void Fl_GDI_Graphics_Driver::uncache(Fl_Bitmap *img, fl_uintptr_t &id_) { + delete_bitmask((Fl_Offscreen)id_); +} + +void Fl_GDI_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + if (pxm->mask_) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)pxm->mask_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); + SelectObject(new_gc, (void*)pxm->id_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } else { + copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); + } +} + + +void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + typedef BOOL (WINAPI* fl_transp_func) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); + static HMODULE hMod = NULL; + static fl_transp_func fl_TransparentBlt = NULL; + if (!hMod) { + hMod = LoadLibrary("MSIMG32.DLL"); + if(hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt"); + } + if (fl_TransparentBlt) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)pxm->id_); + // print all of offscreen but its parts in background color + fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, W, H, pxm->pixmap_bg_color ); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } + else { + copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); + } +} + +fl_uintptr_t Fl_GDI_Printer_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { + Fl_Offscreen id; + id = fl_create_offscreen(w(), h()); + fl_begin_offscreen(id); + uchar *bitmap = 0; + fl_mask_bitmap = &bitmap; + fl_draw_pixmap(data, 0, 0, FL_BLACK); + extern UINT win_pixmap_bg_color; // computed by fl_draw_pixmap() + this->pixmap_bg_color = win_pixmap_bg_color; + fl_mask_bitmap = 0; + if (bitmap) { + img->mask_ = (fl_uintptr_t)fl_create_bitmask(w(), h(), bitmap); + delete[] bitmap; + } + fl_end_offscreen(); + return (fl_uintptr_t)id; +} + // // End of "$Id$". // diff --git a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h index 206b90029..d4e7074fe 100644 --- a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h +++ b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h @@ -25,7 +25,7 @@ #ifndef FL_CFG_GFX_OPENGL_H #define FL_CFG_GFX_OPENGL_H -#include <FL/Fl_Device.H> +#include <FL/Fl_Graphics_Driver.H> /** diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h index f72e8be8d..04d214504 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h @@ -22,14 +22,10 @@ \brief Definition of Apple Quartz graphics driver. */ -#include "../../config_lib.h" -#ifdef FL_CFG_GFX_QUARTZ - #ifndef FL_QUARTZ_GRAPHICS_DRIVER_H #define FL_QUARTZ_GRAPHICS_DRIVER_H -#include <FL/Fl_Device.H> - +#include <FL/Fl_Graphics_Driver.H> // typedef what the x,y fields in a point are: // FIXME: this is still defined in Fl_Device.H, but should be invisible to the user @@ -59,6 +55,10 @@ public: void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); + fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + void uncache(Fl_Bitmap *img, fl_uintptr_t &id_); + void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); #if ! defined(FL_DOXYGEN) static Fl_Offscreen create_offscreen_with_alpha(int w, int h); #endif @@ -122,11 +122,8 @@ protected: int descent(); }; - #endif // FL_QUARTZ_GRAPHICS_DRIVER_H -#endif // FL_CFG_GFX_QUARTZ - // // End of "$Id: quartz.H 11017 2016-01-20 21:40:12Z matt $". // diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx index 442b8b29a..9a2180910 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx @@ -17,7 +17,6 @@ // #include "../../config_lib.h" -#ifdef FL_CFG_GFX_QUARTZ #include "Fl_Quartz_Graphics_Driver.h" @@ -221,12 +220,12 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, // If the CGImage is printed, it is not deallocated until after the end of the page, // therefore, with img->alloc_array != 0, the RGB image can be safely deleted any time after return from this function. // The previously unused mask_ member allows to make sure the RGB image data is not deleted by Fl_RGB_Image::uncache(). - if (img->alloc_array) img->mask_ = new bool(true); - CGDataProviderRef src = CGDataProviderCreateWithData(img->mask_, img->array, ld * img->h(), + if (img->alloc_array) img->mask_ = (fl_uintptr_t)new bool(true); + CGDataProviderRef src = CGDataProviderCreateWithData((void*)img->mask_, img->array, ld * img->h(), img->alloc_array?imgProviderReleaseData:NULL); - img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, - lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, - src, 0L, false, kCGRenderingIntentDefault); + img->id_ = (fl_uintptr_t)CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, + lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, false, kCGRenderingIntentDefault); CGColorSpaceRelease(lut); CGDataProviderRelease(src); } @@ -244,9 +243,9 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, img->uncache(); CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); CGDataProviderRef src = CGDataProviderCreateWithData( NULL, img_bytes, ld * img->h(), imgProviderReleaseData); - img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, - lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, - src, 0L, true, kCGRenderingIntentDefault); + img->id_ = (fl_uintptr_t)CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, + lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, true, kCGRenderingIntentDefault); CGColorSpaceRelease(lut); CGDataProviderRelease(src); } @@ -298,9 +297,31 @@ void Fl_Quartz_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) { if (bm) CGImageRelease((CGImageRef)bm); } +void Fl_Quartz_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { + if (id_) { + if (mask_) *(bool*)mask_ = false; + CGImageRelease((CGImageRef)id_); + id_ = 0; + mask_ = NULL; + } +} + +fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { + return (fl_uintptr_t)create_bitmask(w, h, array); +} +void Fl_Quartz_Graphics_Driver::uncache(Fl_Bitmap*, fl_uintptr_t &id_) { + delete_bitmask((Fl_Bitmask)id_); +} -#endif // FL_CFG_GFX_QUARTZ +fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { + Fl_Offscreen id; + id = create_offscreen_with_alpha(w, h); + fl_begin_offscreen(id); + fl_draw_pixmap(data, 0, 0, FL_BLACK); + fl_end_offscreen(); + return (fl_uintptr_t)id; +} // // End of "$Id$". diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h index bb55c1f53..577f5f573 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h @@ -25,7 +25,7 @@ #ifndef FL_CFG_GFX_XLIB_H #define FL_CFG_GFX_XLIB_H -#include <FL/Fl_Device.H> +#include <FL/Fl_Graphics_Driver.H> /** \brief The Xlib-specific graphics class. @@ -52,6 +52,10 @@ public: void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); + fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + void uncache(Fl_Bitmap *img, fl_uintptr_t &id_); + void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); double width(const char *str, int n); double width(unsigned int c); void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index cf91cb3a7..479696b77 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -624,6 +624,213 @@ void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP XSetFillStyle(fl_display, fl_gc, FillSolid); } + +static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, + int &X, int &Y, int &W, int &H) +{ + // account for current clip region (faster on Irix): + fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if (cx+W > w) W = w-cx; + if (W <= 0) return 1; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if (cy+H > h) H = h-cy; + if (H <= 0) return 1; + return 0; +} + + +// Composite an image with alpha on systems that don't have accelerated +// alpha compositing... +static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { + int ld = img->ld(); + if (ld == 0) ld = img->w() * img->d(); + uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d(); + int srcskip = ld - img->d() * W; + + uchar *dst = new uchar[W * H * 3]; + uchar *dstptr = dst; + + fl_read_image(dst, X, Y, W, H, 0); + + uchar srcr, srcg, srcb, srca; + uchar dstr, dstg, dstb, dsta; + + if (img->d() == 2) { + // Composite grayscale + alpha over RGB... + for (int y = H; y > 0; y--, srcptr+=srcskip) + for (int x = W; x > 0; x--) { + srcg = *srcptr++; + srca = *srcptr++; + + dstr = dstptr[0]; + dstg = dstptr[1]; + dstb = dstptr[2]; + dsta = 255 - srca; + + *dstptr++ = (srcg * srca + dstr * dsta) >> 8; + *dstptr++ = (srcg * srca + dstg * dsta) >> 8; + *dstptr++ = (srcg * srca + dstb * dsta) >> 8; + } + } else { + // Composite RGBA over RGB... + for (int y = H; y > 0; y--, srcptr+=srcskip) + for (int x = W; x > 0; x--) { + srcr = *srcptr++; + srcg = *srcptr++; + srcb = *srcptr++; + srca = *srcptr++; + + dstr = dstptr[0]; + dstg = dstptr[1]; + dstb = dstptr[2]; + dsta = 255 - srca; + + *dstptr++ = (srcr * srca + dstr * dsta) >> 8; + *dstptr++ = (srcg * srca + dstg * dsta) >> 8; + *dstptr++ = (srcb * srca + dstb * dsta) >> 8; + } + } + + fl_draw_image(dst, X, Y, W, H, 3, 0); + + delete[] dst; +} + + +void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + // Don't draw an empty image... + if (!img->d() || !img->array) { + img->draw_empty(XP, YP); + return; + } + if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!img->id_) { + if (img->d() == 1 || img->d() == 3) { + img->id_ = fl_create_offscreen(img->w(), img->h()); + fl_begin_offscreen((Fl_Offscreen)img->id_); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); + fl_end_offscreen(); + } else if (img->d() == 4 && fl_can_do_alpha_blending()) { + img->id_ = (fl_uintptr_t)fl_create_offscreen_with_alpha(img->w(), img->h()); + fl_begin_offscreen((Fl_Offscreen)img->id_); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d() | FL_IMAGE_WITH_ALPHA, + img->ld()); + fl_end_offscreen(); + } + } + if (img->id_) { + if (img->mask_) { + // I can't figure out how to combine a mask with existing region, + // so cut the image down to a clipped rectangle: + int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H); + cx += nx-X; X = nx; + cy += ny-Y; Y = ny; + // make X use the bitmap as a mask: + XSetClipMask(fl_display, fl_gc, img->mask_); + int ox = X-cx; if (ox < 0) ox += img->w(); + int oy = Y-cy; if (oy < 0) oy += img->h(); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + } + + if (img->d() == 4 && fl_can_do_alpha_blending()) + copy_offscreen_with_alpha(X, Y, W, H, img->id_, cx, cy); + else + copy_offscreen(X, Y, W, H, img->id_, cx, cy); + + if (img->mask_) { + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + fl_restore_clip(); + } + } else { + // Composite image with alpha manually each time... + alpha_blend(img, X, Y, W, H, cx, cy); + } +} + +void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) +{ + if (id_) { + fl_delete_offscreen((Fl_Offscreen)id_); + id_ = 0; + } + + if (mask_) { + fl_delete_bitmask((Fl_Bitmask)mask_); + mask_ = 0; + } +} + +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { + return (fl_uintptr_t)create_bitmask(w, h, array); +} + +void Fl_Xlib_Graphics_Driver::uncache(Fl_Bitmap*, fl_uintptr_t &id_) { + delete_bitmask((Fl_Offscreen)id_); +} + + +void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + if (pxm->mask_) { + // make X use the bitmap as a mask: + XSetClipMask(fl_display, fl_gc, pxm->mask_); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + if (clip_region()) { + // At this point, XYWH is the bounding box of the intersection between + // the current clip region and the (portion of the) pixmap we have to draw. + // The current clip region is often a rectangle. But, when a window with rounded + // corners is moved above another window, expose events may create a complex clip + // region made of several (e.g., 10) rectangles. We have to draw only in the clip + // region, and also to mask out the transparent pixels of the image. This can't + // be done in a single Xlib call for a multi-rectangle clip region. Thus, we + // process each rectangle of the intersection between the clip region and XYWH. + // See also STR #3206. + Region r = XRectangleRegion(X,Y,W,H); + XIntersectRegion(r, clip_region(), r); + int X1, Y1, W1, H1; + for (int i = 0; i < r->numRects; i++) { + X1 = r->rects[i].x1; + Y1 = r->rects[i].y1; + W1 = r->rects[i].x2 - r->rects[i].x1; + H1 = r->rects[i].y2 - r->rects[i].y1; + copy_offscreen(X1, Y1, W1, H1, pxm->id_, cx + (X1 - X), cy + (Y1 - Y)); + } + XDestroyRegion(r); + } else { + copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); + } + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + restore_clip(); + } + else copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); +} + +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { + Fl_Offscreen id; + id = fl_create_offscreen(w(), h()); + fl_begin_offscreen(id); + uchar *bitmap = 0; + fl_mask_bitmap = &bitmap; + fl_draw_pixmap(data(), 0, 0, FL_BLACK); + fl_mask_bitmap = 0; + if (bitmap) { + img->mask_ = (fl_uintptr_t)fl_create_bitmask(w(), h(), bitmap); + delete[] bitmap; + } + fl_end_offscreen(); + return (fl_uintptr_t)id; +} + + // // End of "$Id$". // |
