From 26049351e09d75bdf8b35273a76cf65202583fa7 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Thu, 27 May 2010 17:20:18 +0000 Subject: Better device hierarchy with surfaces and graphics drivers. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7617 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Bitmap.H | 7 +- FL/Fl_Device.H | 205 ++++--- FL/Fl_Image.H | 7 +- FL/Fl_Paged_Device.H | 92 +++ FL/Fl_Pixmap.H | 5 +- FL/Fl_PostScript.H | 293 +++++++++ FL/Fl_Printer.H | 215 ++++--- src/Fl_Bitmap.cxx | 109 ++-- src/Fl_Device.cxx | 59 +- src/Fl_Double_Window.cxx | 13 +- src/Fl_GDI_Printer.cxx | 9 +- src/Fl_Image.cxx | 140 ++++- src/Fl_Paged_Device.cxx | 291 +++++++++ src/Fl_Pixmap.cxx | 167 ++++-- src/Fl_PostScript.cxx | 1393 +++++++++++++++++++++++++++++++++++++++++++ src/Fl_Printer.cxx | 34 +- src/Fl_Quartz_Printer.mm | 9 +- src/Fl_cocoa.mm | 12 +- src/Fl_win32.cxx | 10 +- src/Fl_x.cxx | 19 +- src/fl_arc.cxx | 2 +- src/fl_arci.cxx | 4 +- src/fl_color.cxx | 4 +- src/fl_color_mac.cxx | 4 +- src/fl_color_win32.cxx | 4 +- src/fl_curve.cxx | 2 +- src/fl_draw_image.cxx | 8 +- src/fl_draw_image_mac.cxx | 8 +- src/fl_draw_image_win32.cxx | 11 +- src/fl_draw_pixmap.cxx | 84 ++- src/fl_font_mac.cxx | 6 +- src/fl_font_win32.cxx | 11 +- src/fl_font_x.cxx | 6 +- src/fl_font_xft.cxx | 6 +- src/fl_line_style.cxx | 6 +- src/fl_rect.cxx | 47 +- src/fl_vertex.cxx | 28 +- src/ps_image.cxx | 43 +- 38 files changed, 2898 insertions(+), 475 deletions(-) create mode 100644 FL/Fl_Paged_Device.H create mode 100644 FL/Fl_PostScript.H create mode 100644 src/Fl_Paged_Device.cxx create mode 100644 src/Fl_PostScript.cxx diff --git a/FL/Fl_Bitmap.H b/FL/Fl_Bitmap.H index d47a82acf..33f1914a6 100644 --- a/FL/Fl_Bitmap.H +++ b/FL/Fl_Bitmap.H @@ -40,8 +40,10 @@ struct Fl_Menu_Item; (bitmap) images. Images are drawn using the current color. */ class FL_EXPORT Fl_Bitmap : public Fl_Image { - friend class Fl_Device; - public: + friend class Fl_Quartz_Graphics_Driver; + friend class Fl_GDI_Graphics_Driver; + friend class Fl_Xlib_Graphics_Driver; +public: /** pointer to raw bitmap data */ const uchar *array; @@ -58,7 +60,6 @@ class FL_EXPORT Fl_Bitmap : public Fl_Image { unsigned id_; #endif // __APPLE__ || WIN32 - void generic_device_draw(int XP, int YP, int WP, int HP, int cx, int cy); public: /** The constructors create a new bitmap from the specified bitmap data */ diff --git a/FL/Fl_Device.H b/FL/Fl_Device.H index 8eaaa0c87..21251f6c6 100644 --- a/FL/Fl_Device.H +++ b/FL/Fl_Device.H @@ -1,8 +1,8 @@ // // "$Id$" // -// Definition of classes Fl_Device, Fl_Display, Fl_Quartz_Display, Fl_GDI_Display, -// and Fl_Xlib_Display for the Fast Light Tool Kit (FLTK). +// Definition of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device +// for the Fast Light Tool Kit (FLTK). // // Copyright 2010 by Bill Spitzak and others. // @@ -26,7 +26,7 @@ // http://www.fltk.org/str.php // /** \file Fl_Device.H - \brief declaration of classes Fl_Device, Fl_Display. + \brief declaration of classes Fl_Device, Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device. */ #ifndef Fl_Device_H @@ -45,14 +45,15 @@ #include #endif -class Fl_Widget; -class Fl_Device; -class Fl_Display; -class Fl_Abstract_Printer; -/** \brief Points to the device that currently receives all graphics requests */ -FL_EXPORT extern Fl_Device *fl_device; -/** \brief Points to the platform's display device */ -FL_EXPORT extern Fl_Display *fl_display_device; +class Fl_Graphics_Driver; +class Fl_Display_Device; +class Fl_Surface_Device; +/** \brief Points to the driver that currently receives all graphics requests */ +extern Fl_Graphics_Driver *fl_device; +/** \brief Points to the surface that currently receives all graphics requests */ +extern Fl_Surface_Device *fl_surface; +/** \brief Points to the platform's display */ +extern Fl_Display_Device *fl_display_device; /** signature of image generation callback function. @@ -65,33 +66,56 @@ FL_EXPORT extern Fl_Display *fl_display_device; typedef void (*Fl_Draw_Image_Cb)(void* data,int x,int y,int w,uchar* buf); /** - \brief A pure virtual class subclassed to send the output of drawing functions to display, printers, or local files. + \brief All graphical output devices and all graphics systems. + */ +class Fl_Device { +protected: + /** \brief The device type */ + const char *type_; + /** \brief A string that identifies each subclass of Fl_Device. + * + Function type() applied to a device of this class returns this string. + */ + static const char *device_type; +public: + /** + @brief An RTTI emulation of device classes. + * + The type of an instance of an Fl_Device subclass can be checked with code such as: + \code + if ( instance->type() == Fl_Printer::device_type ) { ... } + \endcode + */ + inline const char *type() {return type_;}; +}; + +/** + \brief A virtual class subclassed for each graphics driver FLTK uses. * - The protected virtual methods of this class are those that a device should implement to + The protected virtual methods of this class are those that a graphics driver should implement to support all of FLTK drawing functions.
The preferred FLTK API for drawing operations is the function collection of the \ref fl_drawings and \ref fl_attributes modules. -
Alternatively, member functions of the Fl_Device class can be called - using the global variable Fl_Device * \ref fl_device that points at all time to the single device - (an instance of an Fl_Device subclass) that's currently receiving graphics requests: +
Alternatively, methods of the Fl_Graphics_Driver class can be called + using the global variable Fl_Graphics_Driver * \ref fl_device that points at all time to the single driver + (an instance of an Fl_Graphics_Driver subclass) that's currently receiving graphics requests: \code fl_device->rect(x, y, w, h); \endcode -
Each member function of the Fl_Device class has the same effect and parameter list as the +
Each protected method of the Fl_Graphics_Driver class has the same effect as the function of the \ref fl_drawings and \ref fl_attributes modules which bears the same name - prefixed with fl_ . + prefixed with fl_ and has the same parameter list. */ -class Fl_Device { +class Fl_Graphics_Driver : public Fl_Device { protected: - /** \brief The device type */ - int type_; - /** \brief red color for background and/or mixing if device does not support masking or alpha */ +/* ** \brief red color for background and/or mixing if device does not support masking or alpha * uchar bg_r_; - /** \brief green color for background and/or mixing if device does not support masking or alpha */ + ** \brief green color for background and/or mixing if device does not support masking or alpha * uchar bg_g_; - /** \brief blue color for background and/or mixing if device does not support masking or alpha */ - uchar bg_b_; + ** \brief blue color for background and/or mixing if device does not support masking or alpha * + uchar bg_b_; */ friend class Fl_Pixmap; friend class Fl_Bitmap; friend class Fl_RGB_Image; + friend class Fl_PostScript_Graphics_Driver; friend void fl_rect(int x, int y, int w, int h); friend void fl_rectf(int x, int y, int w, int h); friend void fl_line_style(int style, int width, char* dashes); @@ -141,6 +165,8 @@ protected: friend void fl_draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D); friend FL_EXPORT void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D); + /** \brief The constructor. */ + Fl_Graphics_Driver() {}; /** \brief see fl_rect(int x, int y, int w, int h). */ virtual void rect(int x, int y, int w, int h); /** \brief see fl_rectf(int x, int y, int w, int h). */ @@ -239,74 +265,113 @@ protected: /** \brief see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D). */ virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); // Image classes - virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy); - virtual void draw(Fl_Bitmap * bmp,int XP, int YP, int WP, int HP, int cx, int cy); - virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy); - -public: - /** - @brief All implemented graphics output devices. + /** \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. */ - enum device_types { - xlib_display = 0, /**< The X11 display. */ - quartz_display, /**< The Mac OS X display. */ - gdi_display, /**< The MSWindows display. */ - gdi_printer = 256, /**< The MSWindows printer. */ - quartz_printer, /**< The Mac OS X printer. */ - postscript_device /**< The PostScript device. */ - }; - /** - @brief An RTTI emulation of device classes. It returns values < 256 if it is a display device + 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. */ - inline int type() {return type_;}; - virtual Fl_Device *set_current(void); - - virtual ~Fl_Device() {}; - static Fl_Device *current(); - - /** - @brief Returns the platform's display device. + 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. */ - static Fl_Display *display_device() { return fl_display_device; }; - -}; -extern FL_EXPORT Fl_Device *fl_device; - -/** - @brief A virtual class subclassed for OS-specific display graphics. - */ -class Fl_Display : public Fl_Device { - friend class Fl_PSfile_Device; + virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {}; + +public: + static const char *device_type; + /** \brief The destructor */ + virtual ~Fl_Graphics_Driver() {}; }; #if defined(__APPLE__) || defined(FL_DOXYGEN) /** - @brief The Mac OS X-specific display graphics class. + \brief The Mac OS X-specific graphics class. + * + This class is implemented only on the Mac OS X platform. */ -class Fl_Quartz_Display : public Fl_Display { +class Fl_Quartz_Graphics_Driver : public Fl_Graphics_Driver { public: - Fl_Quartz_Display() { type_ = quartz_display; }; + Fl_Quartz_Graphics_Driver() { type_ = device_type; }; + static const char *device_type; + void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); }; #endif #if defined(WIN32) || defined(FL_DOXYGEN) /** - @brief The MSWindows-specific display graphics class. + \brief The MSWindows-specific graphics class. + * + This class is implemented only on the MSWindows platform. */ -class Fl_GDI_Display : public Fl_Display { +class Fl_GDI_Graphics_Driver : public Fl_Graphics_Driver { public: - Fl_GDI_Display() { type_ = gdi_display; }; + Fl_GDI_Graphics_Driver() { type_ = device_type; }; + static const char *device_type; + void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); }; #endif -#if !( defined(__APPLE__) || defined(WIN32)) || defined(FL_DOXYGEN) +#if !(defined(__APPLE__) || defined(WIN32)) /** - @brief The X11-specific display graphics class. + \brief The Xlib-specific graphics class. + * + This class is implemented only on the Xlib platform. */ -class Fl_Xlib_Display : public Fl_Display { +class Fl_Xlib_Graphics_Driver : public Fl_Graphics_Driver { public: - Fl_Xlib_Display() { type_ = xlib_display; }; + Fl_Xlib_Graphics_Driver() { type_ = device_type; }; + static const char *device_type; + void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); }; #endif +/** + \brief A surface that's susceptible to receive graphical output. + */ +class Fl_Surface_Device : public Fl_Device { + /** \brief The graphics driver in use by this surface. */ + Fl_Graphics_Driver *_driver; +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 *device_type; + 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; }; + /** \brief the surface that currently receives graphics output */ + static Fl_Surface_Device *surface() {return fl_surface; }; + /** \brief The destructor. */ + virtual ~Fl_Surface_Device() {} +}; + +/** + \brief A display to which the computer can draw. + */ +class Fl_Display_Device : public Fl_Surface_Device { +public: + static const char *device_type; + /** \brief A constructor that sets the graphics driver used by the display */ + Fl_Display_Device(Fl_Graphics_Driver *graphics_driver) : Fl_Surface_Device( graphics_driver) { type_ = device_type; }; + /** + @brief Returns the platform's display device. + */ + static Fl_Display_Device *display_device() { return fl_display_device; }; +}; + #endif // Fl_Device_H // diff --git a/FL/Fl_Image.H b/FL/Fl_Image.H index ff10b1ef6..329f3fa44 100644 --- a/FL/Fl_Image.H +++ b/FL/Fl_Image.H @@ -188,9 +188,10 @@ class FL_EXPORT Fl_Image { <FL/Fl_RGB_Image.H> should be included. */ class FL_EXPORT Fl_RGB_Image : public Fl_Image { - friend class Fl_Device; - void generic_device_draw(int X, int Y, int W, int H, int cx=0, int cy=0); - public: + friend class Fl_Quartz_Graphics_Driver; + friend class Fl_GDI_Graphics_Driver; + friend class Fl_Xlib_Graphics_Driver; +public: const uchar *array; int alloc_array; // Non-zero if array was allocated diff --git a/FL/Fl_Paged_Device.H b/FL/Fl_Paged_Device.H new file mode 100644 index 000000000..41d1a5f00 --- /dev/null +++ b/FL/Fl_Paged_Device.H @@ -0,0 +1,92 @@ +// +// "$Id: Fl_Paged_Device.H 7556 2010-04-27 21:33:44Z manolo $" +// +// Printing support for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/** \file Fl_Paged_Device.H + \brief declaration of class Fl_Paged_Device. + */ + +#ifndef Fl_Paged_Device_H +#define Fl_Paged_Device_H + +#include + +/** + \brief Represents page-structured drawing surfaces. + * + This class has no public constructor: don't instantiate it; use Fl_Printer + or Fl_PostScript_File_Device instead. + */ +class Fl_Paged_Device : public Fl_Surface_Device { +private: +#ifdef __APPLE__ + struct chain_elt { + Fl_Image *image; + const uchar *data; + struct chain_elt *next; + }; + void add_image(Fl_Image *image, const uchar *data); // adds an image to the page image list +#endif + void traverse(Fl_Widget *widget); // finds subwindows of widget and prints them +protected: + /** \brief horizontal offset to the origin of graphics coordinates */ + int x_offset; + /** \brief vertical offset to the origin of graphics coordinates */ + int y_offset; + /** \brief chained list of Fl_Image's used in this page */ + struct chain_elt *image_list_; +#ifdef __APPLE__ + /** \brief deletes the page image list */ + void delete_image_list(); +#endif + /** \brief The constructor */ + Fl_Paged_Device() : Fl_Surface_Device(NULL) {type_ = device_type;}; + /** \brief The destructor */ + virtual ~Fl_Paged_Device() {}; +public: + static const char *device_type; + virtual int start_job(int pagecount, int *frompage = NULL, int *topage = NULL); + virtual int start_page(void); + virtual int printable_rect(int *w, int *h); + virtual void margins(int *left, int *top, int *right, int *bottom); + virtual void origin(int x, int y); + void origin(int *x, int *y); + virtual void scale(float scale_x, float scale_y); + virtual void rotate(float angle); + virtual void translate(int x, int y); + virtual void untranslate(void); + void print_widget(Fl_Widget* widget, int delta_x = 0, int delta_y = 0); + void print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x = 0, int delta_y = 0); + virtual int end_page (void); + virtual void end_job (void); +}; + +#endif // Fl_Paged_Device_H + +// +// End of "$Id: Fl_Paged_Device.H 7556 2010-04-27 21:33:44Z manolo $" +// + diff --git a/FL/Fl_Pixmap.H b/FL/Fl_Pixmap.H index 8cab445a5..7391e8341 100644 --- a/FL/Fl_Pixmap.H +++ b/FL/Fl_Pixmap.H @@ -45,7 +45,9 @@ struct Fl_Menu_Item; (pixmap) images, including transparency. */ class FL_EXPORT Fl_Pixmap : public Fl_Image { - friend class Fl_Device; + friend class Fl_Quartz_Graphics_Driver; + friend class Fl_GDI_Graphics_Driver; + friend class Fl_Xlib_Graphics_Driver; void copy_data(); void delete_data(); void set_data(const char * const *p); @@ -67,7 +69,6 @@ class FL_EXPORT Fl_Pixmap : public Fl_Image { unsigned id_; // for internal use unsigned mask_; // for internal use (mask bitmap) #endif // __APPLE__ || WIN32 - void generic_device_draw(int XP, int YP, int WP, int HP, int cx, int cy); public: diff --git a/FL/Fl_PostScript.H b/FL/Fl_PostScript.H new file mode 100644 index 000000000..8d16dc1c6 --- /dev/null +++ b/FL/Fl_PostScript.H @@ -0,0 +1,293 @@ +// +// "$Id: Fl_PostScript.H 7556 2010-04-27 21:33:44Z manolo $" +// +// Support for graphics output to PostScript file for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +/** \file Fl_PostScript.H + \brief declaration of classes Fl_PostScript_Graphics_Driver, Fl_PostScript_File_Device. + */ + + +#ifndef Fl_PostScript_H +#define Fl_PostScript_H + +#include +#include + +#define NO_PAGE_FORMATS 30 /* MSVC6 compilation fix */ + +/** + \brief PostScript graphical backend. + * + PostScript text output is presently implemented only for the latin character set. + FLTK's standard fonts are output using PostScript's standard fonts: Helvetica, Courier, + Times (and their bold, oblique, italic variants), Symbol, ZapfDingbats. + */ +class Fl_PostScript_Graphics_Driver : public Fl_Graphics_Driver { +public: + static const char *device_type; + /** + \brief Possible page formats. + */ + enum Page_Format { + A0 = 0, + A1, + A2, + A3, + A4, + A5, + A6, + A7, + A8, + A9, + B0, + B1, + B2, + B3, + B4, + B5, + B6, + B7, + B8, + B9, + B10, + C5E, + DLE, + EXECUTIVE, + FOLIO, + LEDGER, + LEGAL, + LETTER, + TABLOID, + ENVELOPE, + MEDIA = 0x1000 + }; + + /** + \brief Possible page layouts. + */ + enum Page_Layout {PORTRAIT = 0, LANDSCAPE = 0x100, REVERSED = 0x200, ORIENTATION = 0x300}; + +#ifndef FL_DOXYGEN +public: + enum SHAPE{NONE=0, LINE, LOOP, POLYGON, POINTS}; + +typedef struct page_format { + int width; + int height; + const char *name; +} page_format; + +class Clip { + public: + int x, y, w, h; + Clip *prev; + }; + Clip * clip_; + + int lang_level_; + int font_; + int size_; + Fl_Color color_; + int gap_; + int pages_; + + double width_; + double height_; + + int shape_; + int linewidth_;// need for clipping, lang level 1-2 + int linestyle_;// + int interpolate_; //interpolation of images + unsigned char cr_,cg_,cb_; + char linedash_[256];//should be enough + void concat(); // transform ror scalable dradings... + void reconcat(); //invert + void recover(); //recovers the state after grestore (such as line styles...) + void reset(); + + uchar * mask; + int mx; // width of mask; + int my; // mask lines + //Fl_Color bg_; + int (*close_cmd_)(FILE *); + int page_policy_; + int nPages; + int orientation_; + + float scale_x; + float scale_y; + float angle; + int left_margin; + int top_margin; + + FILE *output; + double pw_, ph_; + static const page_format page_formats[NO_PAGE_FORMATS]; + + uchar bg_r, bg_g, bg_b; + int start_postscript (int pagecount, enum Page_Format format, enum Page_Layout layout); + /* int alpha_mask(const uchar * data, int w, int h, int D, int LD=0); + */ + void draw(const char* s, int n, int x, int y) {transformed_draw(s,n,x,y); }; + void draw(int angle, const char *str, int n, int x, int y); + void transformed_draw(const char* s, int n, double x, double y); //precise text placing + void transformed_draw(const char* s, double x, double y); + int alpha_mask(const uchar * data, int w, int h, int D, int LD=0); + void draw_scaled_image(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D=3, int LD=0); + void draw_scaled_image_mono(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D=3, int LD=0); + void draw_scaled_image(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D); + void draw_scaled_image_mono(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D); + + enum Page_Format page_format_; + char *ps_filename_; + // implementation of drawing methods + void color(Fl_Color c); + //void bg_color(Fl_Color bg); + void color(uchar r, uchar g, uchar b); + Fl_Color color(){return color_;}; + + void push_clip(int x, int y, int w, int h); + int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H); + int not_clipped(int x, int y, int w, int h); + void push_no_clip(); + void pop_clip(); + + void line_style(int style, int width=0, char* dashes=0); + + void rect(int x, int y, int w, int h); + void rectf(int x, int y, int w, int h); + + void xyline(int x, int y, int x1); + void xyline(int x, int y, int x1, int y2); + void xyline(int x, int y, int x1, int y2, int x3); + + void yxline(int x, int y, int y1); + void yxline(int x, int y, int y1, int x2); + void yxline(int x, int y, int y1, int x2, int y3); + + void line(int x1, int y1, int x2, int y2); + void line(int x1, int y1, int x2, int y2, int x3, int y3); + + void loop(int x0, int y0, int x1, int y1, int x2, int y2); + void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); + void polygon(int x0, int y0, int x1, int y1, int x2, int y2); + void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); + void point(int x, int y); + + void begin_points(); + void begin_line(); + void begin_loop(); + void begin_polygon(); + void vertex(double x, double y); + void curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3); + void circle(double x, double y, double r); + void arc(double x, double y, double r, double start, double a); + void arc(int x, int y, int w, int h, double a1, double a2); + void pie(int x, int y, int w, int h, double a1, double a2); + void end_points(); + void end_line(); + void end_loop(); + void end_polygon(); + void begin_complex_polygon(){begin_polygon();}; + void gap(){gap_=1;}; + void end_complex_polygon(){end_polygon();}; + void transformed_vertex(double x, double y); + + void font(int face, int size); + int font(){return font_;}; + int size(){return size_;}; + double width(unsigned c); + double width(const char* s, int n); + int descent(); + int height(); + + void draw_image(const uchar* d, int x,int y,int w,int h, int delta=3, int ldelta=0){draw_scaled_image(d,x,y,w,h,w,h,delta,ldelta);}; + void draw_image_mono(const uchar* d, int x,int y,int w,int h, int delta=1, int ld=0){draw_scaled_image_mono(d,x,y,w,h,w,h,delta,ld);}; + void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3){draw_scaled_image(call,data, x, y, w, h, w, h, delta);}; + void draw_image_mono(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=1){draw_scaled_image_mono(call, data, x, y, w, h, w, h, delta);}; + + void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy); + void draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy); + +public: + void page_policy(int p); + int page_policy(){return page_policy_;}; + void close_command( int (*cmd)(FILE *)){close_cmd_=cmd;}; + FILE * file() {return output;}; + //void orientation (int o); + //Fl_PostScript_Graphics_Driver(FILE *o, int lang_level, int pages = 0); // ps (also multi-page) constructor + //Fl_PostScript_Graphics_Driver(FILE *o, int lang_level, int x, int y, int w, int h); //eps constructor + void interpolate(int i){interpolate_=i;}; + int interpolate(){return interpolate_;} + + void page(double pw, double ph, int media = 0); + void page(int format); + + void place(double x, double y, double tx, double ty, double scale = 1); +#endif // FL_DOXYGEN + Fl_PostScript_Graphics_Driver(); + ~Fl_PostScript_Graphics_Driver(); +}; + +/** + \brief To send graphical output to a PostScript file. + */ +class Fl_PostScript_File_Device : public Fl_Paged_Device { +#ifdef __APPLE__ + CGContextRef gc; +#endif +protected: + Fl_PostScript_Graphics_Driver *driver(); +public: + static const char *device_type; + Fl_PostScript_File_Device(); + ~Fl_PostScript_File_Device(); + int start_job(int pagecount, enum Fl_PostScript_Graphics_Driver::Page_Format format = Fl_PostScript_Graphics_Driver::A4, + enum Fl_PostScript_Graphics_Driver::Page_Layout layout = Fl_PostScript_Graphics_Driver::PORTRAIT); + int start_job(FILE *ps_output, int pagecount, enum Fl_PostScript_Graphics_Driver::Page_Format format = Fl_PostScript_Graphics_Driver::A4, + enum Fl_PostScript_Graphics_Driver::Page_Layout layout = Fl_PostScript_Graphics_Driver::PORTRAIT); + int start_page (void); + int printable_rect(int *w, int *h); + void margins(int *left, int *top, int *right, int *bottom); + void origin(int x, int y); + void scale (float scale_x, float scale_y); + void rotate(float angle); + void translate(int x, int y); + void untranslate(void); + int end_page (void); + void end_job(void); +#ifdef __APPLE__ + void set_current() { fl_gc = gc; Fl_Paged_Device::set_current(); } +#endif + + static const char *file_chooser_title; +}; + +#endif // Fl_PostScript_H + +// +// End of "$Id: Fl_PostScript.H 7556 2010-04-27 21:33:44Z manolo $" +// diff --git a/FL/Fl_Printer.H b/FL/Fl_Printer.H index 8aba8dc81..07b7b5ff3 100644 --- a/FL/Fl_Printer.H +++ b/FL/Fl_Printer.H @@ -25,55 +25,34 @@ // http://www.fltk.org/str.php // /** \file Fl_Printer.H - \brief declaration of classes Fl_Printer, Fl_Device_Plugin. + \brief declaration of classes Fl_System_Printer, Fl_PostScript_Printer, Fl_Printer, Fl_Device_Plugin. */ #ifndef Fl_Printer_H #define Fl_Printer_H -#include +#include #include #include #include #include #include +#if !(defined(__APPLE__) || defined(WIN32)) +#include +#endif #if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN) /** - * @brief Provides an OS-independent interface to printing. - * - It allows to use all FLTK drawing, color, text, and clip functions, and to have them operate - on printed page(s). There are two main, non exclusive, ways to use it. -
  • Print any widget (standard, custom, Fl_Window, Fl_Gl_Window) as it appears - on screen, with optional translation and scaling. This is done by calling print_widget() - or print_window_part(). -
  • Use a series of FLTK graphics commands (e.g., font, text, lines, colors, clip) to - compose a page appropriately shaped for printing. -
- In both cases, begin by start_job(), start_page(), printable_rect() and origin() calls - and finish by end_page() and end_job() calls. -

Platform specifics -

    -
  • Xlib-based platforms (e.g., Linux, Unix): this class is implemented as - a subclass of Fl_PSfile_Device. - Use the static public attributes of this class to set the print dialog to other languages - than English. For example, the "Printer:" dialog item Fl_Printer::dialog_printer can be set to French with: - \code - Fl_Printer::dialog_printer = "Imprimante:"; - Fl_Printer myprinter; - myprinter.start_job(); - \endcode - Use Fl_PSfile_Device::file_chooser_title to customize the title of the file chooser dialog that opens - when using the "Print To File" option of the print dialog. - Class Fl_RGB_Image prints but loses its transparency if it has one. -
  • MSWindows platform: Transparent Fl_RGB_Image 's don't print with exact transparency on most printers. - Fl_RGB_Image 's don't rotate() well. - A workaround is to use the print_window_part() call. -
  • Mac OS X platform: all graphics requests print as on display. -
+ \brief Print support under MSWindows and Mac OS X. +* + Use Fl_Printer instead that is cross-platform and has the same API. + Fl_Printer is typedef'ed to Fl_System_Printer under MSWindows and Mac OS X. */ -class Fl_Printer : public Fl_Abstract_Printer { +class Fl_System_Printer : public Fl_Paged_Device { private: + /** \brief the printer's graphics context, if there's one, NULL otherwise */ + void *gc; + void set_current(); #ifdef __APPLE__ float scale_x; float scale_y; @@ -91,96 +70,174 @@ private: void absolute_printable_rect(int *x, int *y, int *w, int *h); #endif public: + static const char *device_type; /** @brief The constructor. */ - Fl_Printer(void); + Fl_System_Printer(void); int start_job(int pagecount, int *frompage = NULL, int *topage = NULL); int start_page (void); int printable_rect(int *w, int *h); void margins(int *left, int *top, int *right, int *bottom); void origin(int x, int y); -#ifdef FL_DOXYGEN - void origin(int *x, int *y); -#endif void scale (float scale_x, float scale_y); void rotate(float angle); void translate(int x, int y); void untranslate(void); -#ifdef FL_DOXYGEN - void print_widget(Fl_Widget* widget, int delta_x = 0, int delta_y = 0); - void print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x = 0, int delta_y = 0); -#endif int end_page (void); void end_job (void); /** @brief The destructor. */ - ~Fl_Printer(void); - -#else // Xlib (Linux/Unix) - -#include - -class Fl_Printer : public Fl_PSfile_Device { - + ~Fl_System_Printer(void); +#ifndef FL_DOXYGEN public: + static const char *dialog_title; + static const char *dialog_printer; + static const char *dialog_range; + static const char *dialog_copies; + static const char *dialog_all; + static const char *dialog_pages; + static const char *dialog_from; + static const char *dialog_to; + static const char *dialog_properties; + static const char *dialog_copyNo; + static const char *dialog_print_button; + static const char *dialog_cancel_button; + static const char *dialog_print_to_file; + static const char *property_title; + static const char *property_pagesize; + static const char *property_mode; + static const char *property_use; + static const char *property_save; + static const char *property_cancel; +#endif // FL_DOXYGEN +}; // class Fl_System_Printer - Fl_Printer(void) {}; - ~Fl_Printer(void) {}; +/** \brief OS-independant class name */ +typedef Fl_System_Printer Fl_Printer; +#endif + +#if !(defined(__APPLE__) || defined(WIN32)) +/** + \brief Print support under Unix/Linux. + * + Use Fl_Printer instead that is cross-platform and has the same API. + Fl_Printer is typedef'ed to Fl_PostScript_Printer under Unix/Linux. + */ +class Fl_PostScript_Printer : public Fl_PostScript_File_Device { +private: + void set_current(); +public: + static const char *device_type; int start_job(int pages, int *firstpage = NULL, int *lastpage = NULL); -#endif // Fl_Printer (platform-dependent) - - // Fl_Printer:: common for all platforms +#ifndef FL_DOXYGEN + static const char *dialog_title; + static const char *dialog_printer; + static const char *dialog_range; + static const char *dialog_copies; + static const char *dialog_all; + static const char *dialog_pages; + static const char *dialog_from; + static const char *dialog_to; + static const char *dialog_properties; + static const char *dialog_copyNo; + static const char *dialog_print_button; + static const char *dialog_cancel_button; + static const char *dialog_print_to_file; + static const char *property_title; + static const char *property_pagesize; + static const char *property_mode; + static const char *property_use; + static const char *property_save; + static const char *property_cancel; +#endif // FL_DOXYGEN +}; -public: // just to be sure ... +/** \brief OS-independant class name */ +typedef Fl_PostScript_Printer Fl_Printer; +#endif - /** \name These attributes apply to the Xlib platform only. +/** + * @brief OS-independent print support. + * + Fl_Printer allows to use all FLTK drawing, color, text, and clip functions, and to have them operate + on printed page(s). There are two main, non exclusive, ways to use it. +
  • Print any widget (standard, custom, Fl_Window, Fl_Gl_Window) as it appears + on screen, with optional translation and scaling. This is done by calling print_widget() + or print_window_part(). +
  • Use a series of FLTK graphics commands (e.g., font, text, lines, colors, clip) to + compose a page appropriately shaped for printing. +
+ In both cases, begin by start_job(), start_page(), printable_rect() and origin() calls + and finish by end_page() and end_job() calls. +

Platform specifics +
Fl_Printer is typedef'ed to Fl_PostScript_Printer under Unix/Linux + and to Fl_System_Printer otherwise. Both classes have the same API. +

    +
  • Unix/Linux platforms: + Use the static public attributes of this class to set the print dialog to other languages + than English. For example, the "Printer:" dialog item Fl_Printer::dialog_printer can be set to French with: + \code + Fl_Printer::dialog_printer = "Imprimante:"; + Fl_Printer myprinter; + myprinter.start_job(); + \endcode + Use Fl_PostScript_File_Device::file_chooser_title to customize the title of the file chooser dialog that opens + when using the "Print To File" option of the print dialog. + Class Fl_RGB_Image prints but loses its transparency if it has one. +
  • MSWindows platform: Transparent Fl_RGB_Image 's don't print with exact transparency on most printers. + Fl_RGB_Image 's don't rotate() well. + A workaround is to use the print_window_part() call. +
  • Mac OS X platform: all graphics requests print as on display. +
+ */ +#ifdef FL_DOXYGEN +// this class is NOT compiled. It's here for Doxygen documentation purpose only +class Fl_Printer : public Fl_System_Printer, Fl_PostScript_Printer { +public: + static const char *device_type; + Fl_Printer(void); + int start_job(int pagecount, int *frompage = NULL, int *topage = NULL); + int start_page(void); + int printable_rect(int *w, int *h); + void margins(int *left, int *top, int *right, int *bottom); + void origin(int x, int y); + void scale(float scale_x, float scale_y); + void rotate(float angle); + void translate(int x, int y); + void untranslate(void); + int end_page (void); + void end_job (void); + ~Fl_Printer(void); + + /** \name These attributes are effective under the Xlib platform only. \{ */ - /** [this text may be customized at run-time] */ static const char *dialog_title; - /** [this text may be customized at run-time] */ static const char *dialog_printer; - /** [this text may be customized at run-time] */ static const char *dialog_range; - /** [this text may be customized at run-time] */ static const char *dialog_copies; - /** [this text may be customized at run-time] */ static const char *dialog_all; - /** [this text may be customized at run-time] */ static const char *dialog_pages; - /** [this text may be customized at run-time] */ static const char *dialog_from; - /** [this text may be customized at run-time] */ static const char *dialog_to; - /** "Properties..." [this text may be customized at run-time] */ static const char *dialog_properties; - /** [this text may be customized at run-time] */ static const char *dialog_copyNo; - /** [this text may be customized at run-time] */ static const char *dialog_print_button; - /** [this text may be customized at run-time] */ static const char *dialog_cancel_button; - /** [this text may be customized at run-time] */ static const char *dialog_print_to_file; - /** [this text may be customized at run-time] */ static const char *property_title; - /** [this text may be customized at run-time] */ static const char *property_pagesize; - /** [this text may be customized at run-time] */ static const char *property_mode; - /** [this text may be customized at run-time] */ static const char *property_use; - /** [this text may be customized at run-time] */ static const char *property_save; - /** [this text may be customized at run-time] */ static const char *property_cancel; - /** \} */ - -}; // class Fl_Printer + /** \} */ +}; +#endif /** This plugin socket allows the integration of new device drivers for special diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx index 13d5bcaee..d80d810a1 100644 --- a/src/Fl_Bitmap.cxx +++ b/src/Fl_Bitmap.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include "flstring.h" #if defined(__APPLE_QUARTZ__) @@ -251,49 +252,66 @@ void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_device->draw(this, XP, YP, WP, HP, cx, cy); } -void Fl_Bitmap::generic_device_draw(int XP, int YP, int WP, int HP, int cx, int cy) { - if (!array) { - draw_empty(XP, YP); - return; - } - +static int start(Fl_Bitmap *bm, 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): - int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + 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; + 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; + if (cy+H > h) H = h-cy; + if (H <= 0) return 1; + return 0; +} -#if defined(USE_X11) - if (!id_) id_ = fl_create_bitmask(w(), h(), array); +#ifdef __APPLE__ +void Fl_Quartz_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (!bm->array) { + bm->draw_empty(XP, YP); + return; + } + if (start(bm, XP, YP, WP, HP, bm->w(), bm->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!bm->id_) bm->id_ = fl_create_bitmask(bm->w(), bm->h(), bm->array); + if (bm->id_ && fl_gc) { + CGRect rect = { { X, Y }, { W, H } }; + Fl_X::q_begin_image(rect, cx, cy, bm->w(), bm->h()); + CGContextDrawImage(fl_gc, rect, (CGImageRef)bm->id_); + Fl_X::q_end_image(); + } +} - XSetStipple(fl_display, fl_gc, id_); - int ox = X-cx; if (ox < 0) ox += w(); - int oy = Y-cy; if (oy < 0) oy += h(); - XSetTSOrigin(fl_display, fl_gc, ox, oy); - XSetFillStyle(fl_display, fl_gc, FillStippled); - XFillRectangle(fl_display, fl_window, fl_gc, X, Y, W, H); - XSetFillStyle(fl_display, fl_gc, FillSolid); #elif defined(WIN32) - if (!id_) id_ = fl_create_bitmap(w(), h(), array); - +void Fl_GDI_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (!bm->array) { + bm->draw_empty(XP, YP); + return; + } + if (start(bm, XP, YP, WP, HP, bm->w(), bm->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!bm->id_) bm->id_ = fl_create_bitmap(bm->w(), bm->h(), bm->array); + typedef BOOL (WINAPI* fl_transp_func) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); static fl_transp_func fl_TransparentBlt; HDC tempdc; int save; BOOL use_print_algo = false; - if (fl_device->type() == Fl_Device::gdi_printer) { + if (fl_surface->type() == Fl_Printer::device_type) { static HMODULE hMod = NULL; if (!hMod) { hMod = LoadLibrary("MSIMG32.DLL"); if (hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt"); - } - if (hMod) use_print_algo = true; } + if (hMod) use_print_algo = true; + } if (use_print_algo) { // algorithm for bitmap output to Fl_GDI_Printer Fl_Offscreen tmp_id = fl_create_offscreen(W, H); fl_begin_offscreen(tmp_id); @@ -309,37 +327,48 @@ void Fl_Bitmap::generic_device_draw(int XP, int YP, int WP, int HP, int cx, int fl_color(save_c); // back to bitmap's color tempdc = CreateCompatibleDC(fl_gc); save = SaveDC(tempdc); - SelectObject(tempdc, (HGDIOBJ)id_); + SelectObject(tempdc, (HGDIOBJ)bm->id_); SelectObject(fl_gc, fl_brush()); // use bitmap's desired color BitBlt(fl_gc, 0, 0, W, H, tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen fl_end_offscreen(); // offscreen data is in tmp_id SelectObject(tempdc, (HGDIOBJ)tmp_id); // use offscreen data // draw it to printer context with background color as transparent - fl_TransparentBlt(fl_gc, X,Y,W,H, tempdc, cx, cy, w(), h(), RGB(r, g, b) ); + fl_TransparentBlt(fl_gc, X,Y,W,H, tempdc, cx, cy, bm->w(), bm->h(), RGB(r, g, b) ); fl_delete_offscreen(tmp_id); - } + } else { // algorithm for bitmap output to display tempdc = CreateCompatibleDC(fl_gc); save = SaveDC(tempdc); - SelectObject(tempdc, (HGDIOBJ)id_); + SelectObject(tempdc, (HGDIOBJ)bm->id_); SelectObject(fl_gc, fl_brush()); // secret bitblt code found in old MSWindows reference manual: BitBlt(fl_gc, X, Y, W, H, tempdc, cx, cy, 0xE20746L); - } + } RestoreDC(tempdc, save); DeleteDC(tempdc); -#elif defined(__APPLE_QUARTZ__) - if (!id_) id_ = fl_create_bitmask(w(), h(), array); - if (id_ && fl_gc) { - CGRect rect = { { X, Y }, { W, H } }; - Fl_X::q_begin_image(rect, cx, cy, w(), h()); - CGContextDrawImage(fl_gc, rect, (CGImageRef)id_); - Fl_X::q_end_image(); +} + +#else // Xlib +void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (!bm->array) { + bm->draw_empty(XP, YP); + return; } -#else -# error unsupported platform -#endif + if (start(bm, XP, YP, WP, HP, bm->w(), bm->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!bm->id_) bm->id_ = fl_create_bitmask(bm->w(), bm->h(), bm->array); + + XSetStipple(fl_display, fl_gc, bm->id_); + int ox = X-cx; if (ox < 0) ox += bm->w(); + int oy = Y-cy; if (oy < 0) oy += bm->h(); + XSetTSOrigin(fl_display, fl_gc, ox, oy); + XSetFillStyle(fl_display, fl_gc, FillStippled); + XFillRectangle(fl_display, fl_window, fl_gc, X, Y, W, H); + XSetFillStyle(fl_display, fl_gc, FillSolid); } +#endif /** The destructor free all memory and server resources that are used by diff --git a/src/Fl_Device.cxx b/src/Fl_Device.cxx index 9c76d3f6f..a7315552b 100644 --- a/src/Fl_Device.cxx +++ b/src/Fl_Device.cxx @@ -29,51 +29,26 @@ #include #include -/** \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. - */ -void Fl_Device::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { - pxm->generic_device_draw(XP, YP, WP, HP, cx, 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. - */ -void Fl_Device::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { - bm->generic_device_draw(XP, YP, WP, HP, cx, cy); -} +const char *Fl_Device::device_type = "Fl_Device"; +const char *Fl_Surface_Device::device_type = "Fl_Surface_Device"; +const char *Fl_Display_Device::device_type = "Fl_Display_Device"; +const char *Fl_Graphics_Driver::device_type = "Fl_Graphics_Driver"; +#if defined(__APPLE__) || defined(FL_DOXYGEN) +const char *Fl_Quartz_Graphics_Driver::device_type = "Fl_Quartz_Graphics_Driver"; +#endif +#if defined(WIN32) || defined(FL_DOXYGEN) +const char *Fl_GDI_Graphics_Driver::device_type = "Fl_GDI_Graphics_Driver"; +#endif +#if !(defined(__APPLE__) || defined(WIN32)) +const char *Fl_Xlib_Graphics_Driver::device_type = "Fl_Xlib_Graphics_Driver"; +#endif -/** \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. - */ -void Fl_Device::draw(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { - rgb->generic_device_draw(XP, YP, WP, HP, cx, cy); -} - -/** - @brief Sets this device (display, printer, local file) as the target of future graphics calls. - * - @return The current target device of graphics calls. - */ -Fl_Device *Fl_Device::set_current(void) -{ - Fl_Device *current = fl_device; - fl_device = this; - return current; -} -/** - @brief Returns the current target device of graphics calls. - */ -Fl_Device *Fl_Device::current(void) +/** \brief Use this drawing surface for future graphics requests. */ +void Fl_Surface_Device::set_current(void) { - return fl_device; + fl_device = _driver; + fl_surface = this; } // diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx index 89f838844..bd2155329 100644 --- a/src/Fl_Double_Window.cxx +++ b/src/Fl_Double_Window.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -142,18 +143,24 @@ void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) DeleteDC(new_gc); } +//#include void fl_copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { HDC new_gc = CreateCompatibleDC(fl_gc); int save = SaveDC(new_gc); SelectObject(new_gc, bitmap); BOOL alpha_ok = 0; // first try to alpha blend - int to_display = Fl_Device::current()->type() < 256; // true iff display output - if ( (!to_display) || fl_can_do_alpha_blending()) // if not on display, always try alpha_blend + // if to printer, always try alpha_blend + int to_display = Fl_Surface_Device::surface()->type() == Fl_Display_Device::device_type; // true iff display output +//fl_alert("to_display=%d ",to_display); + if ( (to_display && fl_can_do_alpha_blending()) || Fl_Surface_Device::surface()->type() == Fl_Printer::device_type) { alpha_ok = fl_alpha_blend(fl_gc, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc); +//fl_alert("alpha_ok=%d",alpha_ok); + } // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1 - if (!alpha_ok) + if (!alpha_ok) { BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); + } RestoreDC(new_gc, save); DeleteDC(new_gc); } diff --git a/src/Fl_GDI_Printer.cxx b/src/Fl_GDI_Printer.cxx index f89374095..a7fa9fea2 100644 --- a/src/Fl_GDI_Printer.cxx +++ b/src/Fl_GDI_Printer.cxx @@ -34,12 +34,13 @@ extern HWND fl_window; -Fl_Printer::Fl_Printer(void) : Fl_Abstract_Printer() { +Fl_Printer::Fl_System_Printer(void) : Fl_Paged_Device() { hPr = NULL; - type_ = gdi_printer; + type_ = device_type; + driver(fl_device); } -Fl_Printer::~Fl_Printer(void) { +Fl_Printer::~Fl_System_Printer(void) { if (hPr) end_job(); } @@ -117,7 +118,7 @@ int Fl_Printer::start_job (int pagecount, int *frompage, int *topage) void Fl_Printer::end_job (void) { - Fl_Device::display_device()->set_current(); + Fl_Display_Device::display_device()->set_current(); if (hPr != NULL) { if (! abortPrint) { prerr = EndDoc (hPr); diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index bf39f6b09..65636c73c 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -437,7 +437,7 @@ void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_device->draw(this, XP, YP, WP, HP, cx, cy); } -void Fl_RGB_Image::generic_device_draw(int XP, int YP, int WP, int HP, int cx, int cy) { +/*void Fl_RGB_Image::generic_device_draw(int XP, int YP, int WP, int HP, int cx, int cy) { // Don't draw an empty image... if (!d() || !array) { draw_empty(XP, YP); @@ -542,8 +542,146 @@ void Fl_RGB_Image::generic_device_draw(int XP, int YP, int WP, int HP, int cx, i #else # error unsupported platform #endif +}*/ + +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; } +#ifdef __APPLE__ +void Fl_Quartz_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_) { + CGColorSpaceRef lut = 0; + if (img->d()<=2) + lut = CGColorSpaceCreateDeviceGray(); + else + lut = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef src = CGDataProviderCreateWithData( 0L, img->array, img->w()*img->h()*img->d(), 0L); + img->id_ = CGImageCreate( img->w(), img->h(), 8, img->d()*8, img->ld()?img->ld():img->w()*img->d(), + lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, false, kCGRenderingIntentDefault); + CGColorSpaceRelease(lut); + CGDataProviderRelease(src); + } + if (img->id_ && fl_gc) { + CGRect rect = { { X, Y }, { W, H } }; + Fl_X::q_begin_image(rect, cx, cy, img->w(), img->h()); + CGContextDrawImage(fl_gc, rect, (CGImageRef)img->id_); + Fl_X::q_end_image(); + } +} + +#elif defined(WIN32) +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_ = fl_create_offscreen(img->w(), img->h()); + if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { + 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(); + } else { + 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(); + if (img->d() == 2 || img->d() == 4) { + img->mask_ = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array); + } + } + } + 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) { + fl_copy_offscreen_with_alpha(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy); + } else { + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy); + } +} + +#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(); + } + } + 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); + } + + fl_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_Paged_Device.cxx b/src/Fl_Paged_Device.cxx new file mode 100644 index 000000000..52001a060 --- /dev/null +++ b/src/Fl_Paged_Device.cxx @@ -0,0 +1,291 @@ +// +// "$Id: Fl_Paged_Device.cxx 7556 2010-04-27 21:33:44Z manolo $" +// +// implementation of Fl_Paged_Device class for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// +/** \file Fl_Paged_Device.cxx + \brief implementation of class Fl_Paged_Device. + */ + +#include +#include + +const char *Fl_Paged_Device::device_type = "Fl_Paged_Device"; + + +/** + @brief Draws the widget on the printed page. + * + The widget's position on the printed page is determined by the last call to origin() + and by the optional delta_x and delta_y arguments. + Its dimensions are in points unless there was a previous call to scale(). + @param[in] widget Any FLTK widget (e.g., standard, custom, window). + @param[in] delta_x Optional horizontal offset for positioning the widget relatively + to the current origin of graphics functions. + @param[in] delta_y Same as above, vertically. + */ +void Fl_Paged_Device::print_widget(Fl_Widget* widget, int delta_x, int delta_y) +{ + int old_x, old_y, new_x, new_y, is_window; + if ( ! widget->visible() ) return; + is_window = (widget->as_window() != NULL); + widget->damage(FL_DAMAGE_ALL); + // set origin to the desired top-left position of the widget + origin(&old_x, &old_y); + new_x = old_x + delta_x; + new_y = old_y + delta_y; + if (!is_window) { + new_x -= widget->x(); + new_y -= widget->y(); + } + if (new_x != old_x || new_y != old_y) { + translate(new_x - old_x, new_y - old_y ); + } + // if widget is a window, clip all drawings to the window area + if (is_window) fl_push_clip(0, 0, widget->w(), widget->h() ); + // we do some trickery to recognize OpenGL windows and draw them via a plugin + int drawn_by_plugin = 0; + if (widget->as_gl_window()) { + Fl_Plugin_Manager pm("fltk:device"); + Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org"); + if (pi) { + int width, height; + this->printable_rect(&width, &height); + drawn_by_plugin = pi->print(widget, 0, 0, height); + } + } + if (!drawn_by_plugin) { + widget->draw(); + } + if (is_window) fl_pop_clip(); + // find subwindows of widget and print them + traverse(widget); + // reset origin to where it was + if (new_x != old_x || new_y != old_y) { + untranslate(); + } +} + + +void Fl_Paged_Device::traverse(Fl_Widget *widget) +{ + Fl_Group *g = widget->as_group(); + if (!g) return; + int n = g->children(); + for (int i = 0; i < n; i++) { + Fl_Widget *c = g->child(i); + if ( !c->visible() ) continue; + if ( c->as_window() ) { + print_widget(c, c->x(), c->y()); + } + else traverse(c); + } +} + +/** + @brief Computes the page coordinates of the current origin of graphics functions. + * + @param[out] x If non-null, *x is set to the horizontal page offset of graphics origin. + @param[out] y Same as above, vertically. + */ +void Fl_Paged_Device::origin(int *x, int *y) +{ + if (x) *x = x_offset; + if (y) *y = y_offset; +} + +/** + @brief Prints a rectangular part of an on-screen window. + * + @param win The window from where to capture. + @param x The rectangle left + @param y The rectangle top + @param w The rectangle width + @param h The rectangle height + @param delta_x Optional horizontal offset from current graphics origin where to print the captured rectangle. + @param delta_y As above, vertically. + */ +void Fl_Paged_Device::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y) +{ + int slice, width, offset, count = 0; + Fl_Surface_Device *current = Fl_Surface_Device::surface(); + Fl_Display_Device::display_device()->set_current(); + Fl_Window *save_front = Fl::first_window(); + win->show(); + fl_gc = NULL; + Fl::check(); + win->make_current(); + uchar *image_data[20]; +#ifdef WIN32 // because of bug in StretchDIBits, vertically cut image in pieces of width slice + slice = 500; +#else + slice = w; +#endif + for ( offset = 0; offset < w; offset += slice) { + width = slice; + if (offset + width > w) width = w - offset; + image_data[count++] = fl_read_image(NULL, x + offset, y, width, h); + } + save_front->show(); + current->set_current(); + for ( int i = 0, offset = 0; i < count; i++, offset += slice) { + width = slice; + if (offset + width > w) width = w - offset; + fl_draw_image(image_data[i], delta_x + offset, delta_y, width, h, 3); +#ifdef __APPLE__ + add_image(NULL, image_data[i]); +#else + delete image_data[i]; +#endif + } +} + +#ifdef __APPLE__ +void Fl_Paged_Device::add_image(Fl_Image *image, const uchar *data) +{ + struct chain_elt *elt = (struct chain_elt *)calloc(sizeof(struct chain_elt), 1); + elt->image = image; + elt->data = data; + if (image_list_) { elt->next = image_list_; } + image_list_ = elt; +} + +void Fl_Paged_Device::delete_image_list() +{ + while(image_list_) { + struct chain_elt *next = image_list_->next; + if(image_list_->image) delete image_list_->image; + if (image_list_->data) delete (uchar*) image_list_->data; // msvc6 compilation fix + free(image_list_); + image_list_ = next; + } +} +#endif + + +/** + @brief Starts a print job. + * + @param[in] pagecount the total number of pages of the job + @param[out] frompage if non-null, *frompage is set to the first page the user wants printed + @param[out] topage if non-null, *topage is set to the last page the user wants printed + @return 0 iff OK + */ +int Fl_Paged_Device::start_job(int pagecount, int *frompage, int *topage) {return 1;} + +/** + @brief Starts a new printed page + * + The page coordinates are initially in points, i.e., 1/72 inch, + and with origin at the top left of the printable page area. + @return 0 iff OK + */ +int Fl_Paged_Device::start_page (void) {return 1;} + +/** + @brief Computes the width and height of the printable area of the page. + * + Values are in the same unit as that used by FLTK drawing functions, + are unchanged by calls to origin(), but are changed by scale() calls. + Values account for the user-selected paper type and print orientation. + @return 0 iff OK. + */ +int Fl_Paged_Device::printable_rect(int *w, int *h) {return 1;} + +/** + @brief Computes the dimensions of margins that lie between the printable page area and + the full page. + * + Values are in the same unit as that used by FLTK drawing functions. They are changed + by scale() calls. + @param[out] left If non-null, *left is set to the left margin size. + @param[out] top If non-null, *top is set to the top margin size. + @param[out] right If non-null, *right is set to the right margin size. + @param[out] bottom If non-null, *bottom is set to the bottom margin size. + */ +void Fl_Paged_Device::margins(int *left, int *top, int *right, int *bottom) {} + +/** + @brief Sets the position in page coordinates of the origin of graphics functions. + * + Arguments should be expressed relatively to the result of a previous printable_rect() call. + That is, printable_rect(&w, &h); origin(w/2, 0); sets the graphics origin at the + top center of the page printable area. + Origin() calls are not affected by rotate() calls. + Successive origin() calls don't combine their effects. + @param[in] x Horizontal position in page coordinates of the desired origin of graphics functions. + @param[in] y Same as above, vertically. + */ +void Fl_Paged_Device::origin(int x, int y) {} + +/** + @brief Changes the scaling of page coordinates. + * + This function also resets the origin of graphics functions at top left of printable page area. + After a scale() call, do a printable_rect() call to get the new dimensions of the printable page area. + Successive scale() calls don't combine their effects. + @param scale_x Horizontal dimensions of plot are multiplied by this quantity. + @param scale_y Same as above, vertically. + */ +void Fl_Paged_Device::scale (float scale_x, float scale_y) {} + +/** + @brief Rotates the graphics operations relatively to paper. + * + The rotation is centered on the current graphics origin. + Successive rotate() calls don't combine their effects. + @param angle Rotation angle in counterclockwise degrees. + */ +void Fl_Paged_Device::rotate(float angle) {} + +/** + @brief To be called at the end of each page. + * + @return 0 iff OK. + */ +int Fl_Paged_Device::end_page (void) {return 1;} + +/** + @brief To be called at the end of a print job. + */ +void Fl_Paged_Device::end_job (void) {} + +/** + @brief Translates the current graphics origin accounting for the current rotation. + * + This function is only useful after a rotate() call. + Each translate() call must be matched by an untranslate() call. + Successive translate() calls add up their effects. + */ +void Fl_Paged_Device::translate(int x, int y) {} + +/** + @brief Undoes the effect of a previous translate() call. + */ +void Fl_Paged_Device::untranslate(void) {} + +// +// End of "$Id: Fl_Paged_Device.cxx 7556 2010-04-27 21:33:44Z manolo $". +// + diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx index d20132a35..a6049760a 100644 --- a/src/Fl_Pixmap.cxx +++ b/src/Fl_Pixmap.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include #include "flstring.h" @@ -77,121 +78,161 @@ void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_device->draw(this, XP, YP, WP, HP, cx, cy); } -void Fl_Pixmap::generic_device_draw(int XP, int YP, int WP, int HP, int cx, int cy) { +static int start(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int w, int h, int cx, int cy, + int &X, int &Y, int &W, int &H) +{ // ignore empty or bad pixmap data: - if (!data()) { - draw_empty(XP, YP); - return; + if (!pxm->data()) { + return 2; } - if (w()<0) measure(); - if (WP==-1) { - WP = w(); - HP = h(); + if (WP == -1) { + WP = w; + HP = h; } - if (!w()) { - draw_empty(XP, YP); - return; + if (!w) { + return 2; } // account for current clip region (faster on Irix): - int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + 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; + 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; - if (!id_) { -#ifdef __APPLE_QUARTZ__ - id_ = fl_create_offscreen_with_alpha(w(), h()); - fl_begin_offscreen((Fl_Offscreen)id_); - fl_draw_pixmap(data(), 0, 0, FL_GREEN); + if (cy+H > h) H = h-cy; + if (H <= 0) return 1; + return 0; +} + +#ifdef __APPLE__ +void Fl_Quartz_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->w() < 0) pxm->measure(); + int code = start(pxm, XP, YP, WP, HP, pxm->w(), pxm->h(), cx, cy, X, Y, W, H); + if (code) { + if (code == 2) pxm->draw_empty(XP, YP); + return; + } + if (!pxm->id_) { + pxm->id_ = fl_create_offscreen_with_alpha(pxm->w(), pxm->h()); + fl_begin_offscreen((Fl_Offscreen)pxm->id_); + fl_draw_pixmap(pxm->data(), 0, 0, FL_GREEN); fl_end_offscreen(); -#else - id_ = fl_create_offscreen(w(), h()); - fl_begin_offscreen((Fl_Offscreen)id_); + } + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); +} + +#elif defined(WIN32) +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->w() < 0) pxm->measure(); + int code = start(pxm, XP, YP, WP, HP, pxm->w(), pxm->h(), cx, cy, X, Y, W, H); + if (code) { + if (code == 2) pxm->draw_empty(XP, YP); + return; + } + if (!pxm->id_) { + pxm->id_ = fl_create_offscreen(pxm->w(), pxm->h()); + fl_begin_offscreen((Fl_Offscreen)pxm->id_); uchar *bitmap = 0; fl_mask_bitmap = &bitmap; - fl_draw_pixmap(data(), 0, 0, FL_BLACK); + fl_draw_pixmap(pxm->data(), 0, 0, FL_BLACK); fl_mask_bitmap = 0; if (bitmap) { - mask_ = fl_create_bitmask(w(), h(), bitmap); + pxm->mask_ = fl_create_bitmask(pxm->w(), pxm->h(), bitmap); delete[] bitmap; } fl_end_offscreen(); -#endif - } - -#if defined(USE_X11) - if (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, mask_); - int ox = X-cx; if (ox < 0) ox += w(); - int oy = Y-cy; if (oy < 0) oy += h(); - XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); } - fl_copy_offscreen(X, Y, W, H, id_, cx, cy); - if (mask_) { - // put the old clip region back - XSetClipOrigin(fl_display, fl_gc, 0, 0); - fl_restore_clip(); - } -#elif defined(WIN32) - if (fl_device->type() == Fl_Device::gdi_printer) { + if (fl_surface->type() == Fl_Printer::device_type) { 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 (hMod) { - Fl_Offscreen tmp_id = fl_create_offscreen(w(), h()); + Fl_Offscreen tmp_id = fl_create_offscreen(pxm->w(), pxm->h()); fl_begin_offscreen(tmp_id); uchar *bitmap = 0; fl_mask_bitmap = &bitmap; // draw pixmap to offscreen - fl_draw_pixmap(data(), 0, 0); + fl_draw_pixmap(pxm->data(), 0, 0); fl_end_offscreen(); HDC new_gc = CreateCompatibleDC(fl_gc); int save = SaveDC(new_gc); SelectObject(new_gc, (void*)tmp_id); // print all of offscreen but its parts in background color extern UINT win_pixmap_bg_color; // computed by fl_draw_pixmap() - fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, w(), h(), win_pixmap_bg_color ); + fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, pxm->w(), pxm->h(), win_pixmap_bg_color ); RestoreDC(new_gc,save); DeleteDC(new_gc); fl_delete_offscreen(tmp_id); } else { - fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id_, cx, cy); + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); } } - else if (mask_) { + else if (pxm->mask_) { HDC new_gc = CreateCompatibleDC(fl_gc); int save = SaveDC(new_gc); - SelectObject(new_gc, (void*)mask_); + SelectObject(new_gc, (void*)pxm->mask_); BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); - SelectObject(new_gc, (void*)id_); + 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 { - fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id_, cx, cy); + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); } -#elif defined(__APPLE_QUARTZ__) - fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id_, cx, cy); -#else -# error unsupported platform -#endif } +#else // 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->w() < 0) pxm->measure(); + int code = start(pxm, XP, YP, WP, HP, pxm->w(), pxm->h(), cx, cy, X, Y, W, H); + if (code) { + if (code == 2) pxm->draw_empty(XP, YP); + return; + } + if (!pxm->id_) { + pxm->id_ = fl_create_offscreen(pxm->w(), pxm->h()); + fl_begin_offscreen((Fl_Offscreen)pxm->id_); + uchar *bitmap = 0; + fl_mask_bitmap = &bitmap; + fl_draw_pixmap(pxm->data(), 0, 0, FL_BLACK); + fl_mask_bitmap = 0; + if (bitmap) { + pxm->mask_ = fl_create_bitmask(pxm->w(), pxm->h(), bitmap); + delete[] bitmap; + } + fl_end_offscreen(); + } + if (pxm->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, pxm->mask_); + int ox = X-cx; if (ox < 0) ox += pxm->w(); + int oy = Y-cy; if (oy < 0) oy += pxm->h(); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + } + fl_copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); + if (pxm->mask_) { + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + fl_restore_clip(); + } +} + +#endif + /** The destructor free all memory and server resources that are used by the pixmap. diff --git a/src/Fl_PostScript.cxx b/src/Fl_PostScript.cxx new file mode 100644 index 000000000..18ae75385 --- /dev/null +++ b/src/Fl_PostScript.cxx @@ -0,0 +1,1393 @@ +// +// "$Id: Fl_PS_Printer.cxx 7520 2010-04-16 20:19:09Z manolo $" +// +// PostScript device support for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include +#include +#include +#include +#include +#include + +const char *Fl_PostScript_Graphics_Driver::device_type = "Fl_PostScript_Graphics_Driver"; +const char *Fl_PostScript_File_Device::device_type = "Fl_PostScript_File_Device"; +/** \brief Label of the PostScript file chooser window */ +const char *Fl_PostScript_File_Device::file_chooser_title = "Select a .ps file"; + +/** + @brief The constructor. + */ +Fl_PostScript_Graphics_Driver::Fl_PostScript_Graphics_Driver(void) +{ + close_cmd_ = 0; + //lang_level_ = 3; + lang_level_ = 2; + mask = 0; + ps_filename_ = NULL; + type_ = device_type; + scale_x = scale_y = 1.; + bg_r = bg_g = bg_b = 255; +} + +/** \brief The destructor. */ +Fl_PostScript_Graphics_Driver::~Fl_PostScript_Graphics_Driver() { + if(ps_filename_) free(ps_filename_); +} + +/** + @brief The constructor. + */ +Fl_PostScript_File_Device::Fl_PostScript_File_Device(void) +{ + type_ = device_type; +#ifdef __APPLE__ + gc = fl_gc; // the display context is used by fl_text_extents() +#endif + Fl_Surface_Device::driver( new Fl_PostScript_Graphics_Driver() ); +} + +/** + \brief Returns the PostScript driver of this drawing surface. + */ +Fl_PostScript_Graphics_Driver *Fl_PostScript_File_Device::driver() +{ + return (Fl_PostScript_Graphics_Driver*)Fl_Surface_Device::driver(); +} + + +/** + @brief Begins the session where all graphics requests will go to a local PostScript file. + * + Opens a file dialog entitled with Fl_PostScript_File_Device::file_chooser_title to select an output PostScript file. + @param pagecount The total number of pages to be created. + @param format Desired page format. + @param layout Desired page layout. + @return 0 iff OK, 1 if user cancelled the file dialog, 2 if fopen failed on user-selected output file. + */ +int Fl_PostScript_File_Device::start_job (int pagecount, enum Fl_PostScript_Graphics_Driver::Page_Format format, enum Fl_PostScript_Graphics_Driver::Page_Layout layout) +{ + Fl_Native_File_Chooser fnfc; + fnfc.title(Fl_PostScript_File_Device::file_chooser_title); + fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM); + fnfc.filter("PostScript\t*.ps\n"); + // Show native chooser + if ( fnfc.show() ) return 1; + Fl_PostScript_Graphics_Driver *ps = driver(); + ps->output = fopen(fnfc.filename(), "w"); + if(ps->output == NULL) return 2; + ps->ps_filename_ = strdup(fnfc.filename()); + ps->start_postscript(pagecount, format, layout); + this->set_current(); + return 0; +} + +/** + @brief Begins the session where all graphics requests will go to FILE pointer. + * + @param ps_output A writable FILE pointer that will receive PostScript output and that will be closed + when end_job() will be called. + @param pagecount The total number of pages to be created. + @param format Desired page format. + @param layout Desired page layout. + @return always 0. + */ +int Fl_PostScript_File_Device::start_job (FILE *ps_output, int pagecount, enum Fl_PostScript_Graphics_Driver::Page_Format format, enum Fl_PostScript_Graphics_Driver::Page_Layout layout) +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + ps->output = ps_output; + ps->ps_filename_ = NULL; + ps->start_postscript(pagecount, format, layout); + this->set_current(); + return 0; +} + +/** + @brief The destructor. + */ +Fl_PostScript_File_Device::~Fl_PostScript_File_Device() { + Fl_PostScript_Graphics_Driver *ps = driver(); + if (ps) delete ps; +} + +#ifndef FL_DOXYGEN + +#if ! (defined(__APPLE__) || defined(WIN32) ) + #include "print_panel.cxx" +#endif + +const Fl_PostScript_Graphics_Driver::page_format Fl_PostScript_Graphics_Driver::page_formats[NO_PAGE_FORMATS] = { // order of enum Page_Format +// comes from appendix B of 5003.PPD_Spec_v4.3.pdf + + // A* // index(Ai) = i + {2384, 3370, "A0"}, + {1684, 2384, "A1"}, + {1191, 1684, "A2"}, + { 842, 1191, "A3"}, + { 595, 842, "A4"}, + { 420, 595, "A5"}, + { 297, 420, "A6"}, + { 210, 297, "A7"}, + { 148, 210, "A8"}, + { 105, 148, "A9"}, + + // B* // index(Bi) = i+10 + {2920, 4127, "B0"}, + {2064, 2920, "B1"}, + {1460, 2064, "B2"}, + {1032, 1460, "B3"}, + { 729, 1032, "B4"}, + { 516, 729, "B5"}, + { 363, 516, "B6"}, + { 258, 363, "B7"}, + { 181, 258, "B8"}, + { 127, 181, "B9"}, + { 91, 127, "B10"}, + + // others + { 459, 649, "EnvC5"}, // envelope + { 312, 624, "EnvDL"}, // envelope + { 522, 756, "Executive"}, + { 595, 935, "Folio"}, + {1224, 792, "Ledger"}, // landscape + { 612, 1008, "Legal"}, + { 612, 792, "Letter"}, + { 792, 1224, "Tabloid"}, + { 297, 684, "Env10"} // envelope +}; + +// Prolog string + +static const char * prolog = +"%%BeginProlog\n" +"/L { /y2 exch def\n" +"/x2 exch def\n" +"/y1 exch def\n" +"/x1 exch def\n" +"newpath x1 y1 moveto x2 y2 lineto\n" +"stroke}\n" +"bind def\n" + + +"/R { /dy exch def\n" +"/dx exch def\n" +"/y exch def\n" +"/x exch def\n" +"newpath\n" +"x y moveto\n" +"dx 0 rlineto\n" +"0 dy rlineto\n" +"dx neg 0 rlineto\n" +"closepath stroke\n" +"} bind def\n" + +"/CL {\n" +"/dy exch def\n" +"/dx exch def\n" +"/y exch def\n" +"/x exch def\n" +"newpath\n" +"x y moveto\n" +"dx 0 rlineto\n" +"0 dy rlineto\n" +"dx neg 0 rlineto\n" +"closepath\n" +"clip\n" +"} bind def\n" + +"/FR { /dy exch def\n" +"/dx exch def\n" +"/y exch def\n" +"/x exch def\n" +"currentlinewidth 0 setlinewidth newpath\n" +"x y moveto\n" +"dx 0 rlineto\n" +"0 dy rlineto\n" +"dx neg 0 rlineto\n" +"closepath fill setlinewidth\n" +"} bind def\n" + +"/GS { gsave } bind def\n" +"/GR { grestore } bind def\n" + +"/SP { showpage } bind def\n" +"/LW { setlinewidth } bind def\n" +"/CF /Courier def\n" +"/SF { /CF exch def } bind def\n" +"/fsize 12 def\n" +"/FS { /fsize exch def fsize CF findfont exch scalefont setfont }def \n" + + +"/GL { setgray } bind def\n" +"/SRGB { setrgbcolor } bind def\n" + +// color images + +"/CI { GS /py exch def /px exch def /sy exch def /sx exch def\n" +"translate \n" +"sx sy scale px py 8 \n" +"[ px 0 0 py neg 0 py ]\n" +"currentfile /ASCIIHexDecode filter\n false 3" +" colorimage GR\n" +"} bind def\n" + +// gray images + +"/GI { GS /py exch def /px exch def /sy exch def /sx exch def \n" +"translate \n" +"sx sy scale px py 8 \n" + + +"[ px 0 0 py neg 0 py ]\n" +"currentfile /ASCIIHexDecode filter\n" +"image GR\n" +"} bind def\n" + +// single-color bitmask + +"/MI { GS /py exch def /px exch def /sy exch def /sx exch def \n" +"translate \n" +"sx sy scale px py false \n" +"[ px 0 0 py neg 0 py ]\n" +"currentfile /ASCIIHexDecode filter\n" +"imagemask GR\n" +"} bind def\n" + + +// path + +"/BFP { newpath moveto } def\n" +"/BP { newpath } bind def \n" +"/PL { lineto } bind def \n" +"/PM { moveto } bind def \n" +"/MT { moveto } bind def \n" +"/LT { lineto } bind def \n" +"/EFP { closepath fill } bind def\n" //was:stroke +"/ELP { stroke } bind def\n" +"/ECP { closepath stroke } bind def\n" // Closed (loop) +"/LW { setlinewidth } bind def\n" + +// ////////////////////////// misc //////////////// +"/TR { translate } bind def\n" +"/CT { concat } bind def\n" +"/RCT { matrix invertmatrix concat} bind def\n" +"/SC { scale } bind def\n" +//"/GPD { currentpagedevice /PageSize get} def\n" + +// show at position with desired width +// usage: +// width (string) x y show_pos_width +"/show_pos_width {GS moveto dup dup stringwidth pop exch length exch 3 index exch sub exch " +"div 0 2 index 1 -1 scale ashow pop pop GR} bind def\n" // spacing altered to match desired width +//"/show_pos_width {GS moveto dup stringwidth pop 3 2 roll exch div -1 matrix scale concat " +//"show GR } bind def\n" // horizontally scaled text to match desired width + +; + + +static const char * prolog_2 = // prolog relevant only if lang_level >1 + +// color image dictionaries +"/CII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n" +"translate \n" +"sx sy scale\n" +"/DeviceRGB setcolorspace\n" +"/IDD 8 dict def\n" +"IDD begin\n" +"/ImageType 1 def\n" +"/Width px def\n" +"/Height py def\n" +"/BitsPerComponent 8 def\n" +"/Interpolate inter def\n" +"/DataSource currentfile /ASCIIHexDecode filter def\n" +"/MultipleDataSources false def\n" +"/ImageMatrix [ px 0 0 py neg 0 py ] def\n" +"/Decode [ 0 1 0 1 0 1 ] def\n" +"end\n" +"IDD image GR} bind def\n" + +// gray image dict + + +"/GII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n" +"translate \n" +"sx sy scale\n" +"/DeviceGray setcolorspace\n" +"/IDD 8 dict def\n" +"IDD begin\n" +"/ImageType 1 def\n" +"/Width px def\n" +"/Height py def\n" +"/BitsPerComponent 8 def\n" + +"/Interpolate inter def\n" +"/DataSource currentfile /ASCIIHexDecode filter def\n" +"/MultipleDataSources false def\n" +"/ImageMatrix [ px 0 0 py neg 0 py ] def\n" +"/Decode [ 0 1 ] def\n" +"end\n" +"IDD image GR} bind def\n" + +; + +static const char * prolog_2_pixmap = // prolog relevant only if lang_level == 2 for pixmaps +"/pixmap_size { /pixmap_sy exch def /pixmap_sx exch def } bind def\n" + +"/pixmap_mat {[ pixmap_sx 0 0 pixmap_sy neg 0 pixmap_sy ]} bind def\n" + +"/pixmap_dict {" +"<< /PatternType 1 " +"/PaintType 1 " +"/TilingType 2 " +"/BBox [0 0 pixmap_sx pixmap_sy] " +"/XStep pixmap_sx " +"/YStep pixmap_sy\n" +"/PaintProc " +"{ begin " +"pixmap_sx pixmap_sy scale " +"pixmap_sx pixmap_sy 8 " +"pixmap_mat " +"pixmap_data " +"false 3 " +"colorimage " +"end " +"} bind " +">>\n" +"} bind def\n" + +"/pixmap_plot {" +"GS " +"/pixmap_y exch def /pixmap_x exch def\n" +"pixmap_x pixmap_y translate\n" +"pixmap_dict matrix makepattern setpattern\n" +"pixmap_sx pixmap_sy scale\n" +"pixmap_sx pixmap_sy\n" +"true\n" +"pixmap_mat\n" +"pixmap_mask\n" +"imagemask\n" +"GR\n" +"} bind def\n" + +"/pixmap_loaddata { /pixmap_data currentfile pixmap_sx pixmap_sy 3 mul mul string readhexstring " +"} bind def\n" + +"/pixmap_loadmask { " +"/pixmap_mask currentfile pixmap_sx 8 div ceiling cvi pixmap_sy mul string readhexstring " +"} bind def\n" +; + + + +static const char * prolog_3 = // prolog relevant only if lang_level >2 + +// masked color images +"/CIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n" +"translate \n" +"sx sy scale\n" +"/DeviceRGB setcolorspace\n" + +"/IDD 8 dict def\n" + +"IDD begin\n" +"/ImageType 1 def\n" +"/Width px def\n" +"/Height py def\n" +"/BitsPerComponent 8 def\n" +"/Interpolate inter def\n" +"/DataSource currentfile /ASCIIHexDecode filter def\n" +"/MultipleDataSources false def\n" +"/ImageMatrix [ px 0 0 py neg 0 py ] def\n" + +"/Decode [ 0 1 0 1 0 1 ] def\n" +"end\n" + +"/IMD 8 dict def\n" +"IMD begin\n" +"/ImageType 1 def\n" +"/Width mx def\n" +"/Height my def\n" +"/BitsPerComponent 1 def\n" +// "/Interpolate inter def\n" +"/ImageMatrix [ mx 0 0 my neg 0 my ] def\n" +"/Decode [ 1 0 ] def\n" +"end\n" + +"<<\n" +"/ImageType 3\n" +"/InterleaveType 2\n" +"/MaskDict IMD\n" +"/DataDict IDD\n" +">> image GR\n" +"} bind def\n" + + +// masked gray images +"/GIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n" +"translate \n" +"sx sy scale\n" +"/DeviceGray setcolorspace\n" + +"/IDD 8 dict def\n" + +"IDD begin\n" +"/ImageType 1 def\n" +"/Width px def\n" +"/Height py def\n" +"/BitsPerComponent 8 def\n" +"/Interpolate inter def\n" +"/DataSource currentfile /ASCIIHexDecode filter def\n" +"/MultipleDataSources false def\n" +"/ImageMatrix [ px 0 0 py neg 0 py ] def\n" + +"/Decode [ 0 1 ] def\n" +"end\n" + +"/IMD 8 dict def\n" + +"IMD begin\n" +"/ImageType 1 def\n" +"/Width mx def\n" +"/Height my def\n" +"/BitsPerComponent 1 def\n" +"/ImageMatrix [ mx 0 0 my neg 0 my ] def\n" +"/Decode [ 1 0 ] def\n" +"end\n" + +"<<\n" +"/ImageType 3\n" +"/InterleaveType 2\n" +"/MaskDict IMD\n" +"/DataDict IDD\n" +">> image GR\n" +"} bind def\n" + + +"\n" +; + +// end prolog + +int Fl_PostScript_Graphics_Driver::start_postscript (int pagecount, enum Fl_PostScript_Graphics_Driver::Page_Format format, enum Fl_PostScript_Graphics_Driver::Page_Layout layout) +//returns 0 iff OK +{ + int w, h, x; + if (format == A4) { + left_margin = 18; + top_margin = 18; + } + else { + left_margin = 12; + top_margin = 12; + } + page_format_ = (enum Page_Format)(format | layout); + + fputs("%!PS-Adobe-3.0\n", output); + fputs("%%Creator: FLTK\n", output); + if (lang_level_>1) + fprintf(output, "%%%%LanguageLevel: %i\n" , lang_level_); + if ((pages_ = pagecount)) + fprintf(output, "%%%%Pages: %i\n", pagecount); + else + fputs("%%Pages: (atend)\n", output); + fprintf(output, "%%%%BeginFeature: *PageSize %s\n", page_formats[format].name ); + w = page_formats[format].width; + h = page_formats[format].height; + if (lang_level_ == 3 && (layout & LANDSCAPE) ) { x = w; w = h; h = x; } + fprintf(output, "<>setpagedevice\n", w, h ); + fputs("%%EndFeature\n", output); + fputs("%%EndComments\n", output); + fputs(prolog, output); + if (lang_level_ > 1) { + fputs(prolog_2, output); + } + if (lang_level_ == 2) { + fputs(prolog_2_pixmap, output); + } + if (lang_level_ > 2) + fputs(prolog_3, output); + if (lang_level_ >= 3) { + fputs("/CS { clipsave } bind def\n", output); + fputs("/CR { cliprestore } bind def\n", output); + } else { + fputs("/CS { GS } bind def\n", output); + fputs("/CR { GR } bind def\n", output); + } + page_policy_ = 1; + + + fputs("%%EndProlog\n",output); + if (lang_level_ >= 2) + fprintf(output,"<< /Policies << /Pagesize 1 >> >> setpagedevice\n"); + + reset(); + nPages=0; + return 0; +} + +void Fl_PostScript_Graphics_Driver::recover(){ + color(cr_,cg_,cb_); + line_style(linestyle_,linewidth_,linedash_); + font(font_,size_); +} + +void Fl_PostScript_Graphics_Driver::reset(){ + gap_=1; + clip_=0; + cr_=cg_=cb_=0; + font_=FL_HELVETICA; + size_=12; + linewidth_=0; + linestyle_=FL_SOLID; + strcpy(linedash_,""); + Clip *c=clip_; ////just not to have memory leaks for badly writen code (forgotten clip popping) + + while(c){ + clip_=clip_->prev; + delete c; + c=clip_; + } + +} + +void Fl_PostScript_Graphics_Driver::page_policy(int p){ + page_policy_ = p; + if(lang_level_>=2) + fprintf(output,"<< /Policies << /Pagesize %i >> >> setpagedevice\n", p); +} + +// //////////////////// paging ////////////////////////////////////////// + + + +void Fl_PostScript_Graphics_Driver::page(double pw, double ph, int media) { + + if (nPages){ + fprintf(output, "CR\nGR\nGR\nGR\nSP\nrestore\n"); + } + ++nPages; + fprintf(output, "%%%%Page: %i %i\n" , nPages , nPages); + if (pw>ph){ + fprintf(output, "%%%%PageOrientation: Landscape\n"); + }else{ + fprintf(output, "%%%%PageOrientation: Portrait\n"); + } + + fprintf(output, "%%%%BeginPageSetup\n"); + if((media & MEDIA) &&(lang_level_>1)){ + int r = media & REVERSED; + if(r) r = 2; + fprintf(output, "<< /PageSize [%i %i] /Orientation %i>> setpagedevice\n", (int)(pw+.5), (int)(ph+.5), r); + } + fprintf(output, "%%%%EndPageSetup\n"); + + pw_ = pw; + ph_ = ph; + reset(); + + fprintf(output, "save\n"); + fprintf(output, "GS\n"); + fprintf(output, "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); + fprintf(output, "1 -1 SC\n"); + line_style(0); + fprintf(output, "GS\n"); + + if (!((media & MEDIA) &&(lang_level_>1))){ + if (pw > ph) { + if(media & REVERSED) { + fprintf(output, "-90 rotate %i 0 translate\n", int(-pw)); + } + else { + fprintf(output, "90 rotate -%i -%i translate\n", (lang_level_ == 2 ? int(pw - ph) : 0), int(ph)); + } + } + else { + if(media & REVERSED) + fprintf(output, "180 rotate %i %i translate\n", int(-pw), int(-ph)); + } + } + fprintf(output, "GS\nCS\n"); +}; + +void Fl_PostScript_Graphics_Driver::page(int format){ + + + if(format & LANDSCAPE){ + ph_=Fl_PostScript_Graphics_Driver::page_formats[format & 0xFF].width; + pw_=Fl_PostScript_Graphics_Driver::page_formats[format & 0xFF].height; + }else{ + pw_=Fl_PostScript_Graphics_Driver::page_formats[format & 0xFF].width; + ph_=Fl_PostScript_Graphics_Driver::page_formats[format & 0xFF].height; + } + page(pw_,ph_,format & 0xFF00);//,orientation only; +}; + +void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) { + // Commented code does not work, i can't find the bug ;-( + // fprintf(output, "GS\n"); + // fprintf(output, "%i, %i, %i, %i R\n", x , y , w, h); + // fprintf(output, "GR\n"); + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x , y); + fprintf(output, "%i %i LT\n", x+w-1 , y); + fprintf(output, "%i %i LT\n", x+w-1 , y+h-1); + fprintf(output, "%i %i LT\n", x , y+h-1); + fprintf(output, "ECP\n"); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) { + fprintf(output, "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); +} + +void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) { + fprintf(output, "GS\n"); + fprintf(output, "%i %i %i %i L\n", x1 , y1, x2 ,y2); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) { + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x0 , y0); + fprintf(output, "%i %i LT\n", x1 , y1); + fprintf(output, "%i %i LT\n", x2 , y2); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3){ + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x , y ); + fprintf(output, "%i %i LT\n", x1 , y ); + fprintf(output, "%i %i LT\n", x1 , y2); + fprintf(output,"%i %i LT\n", x3 , y2); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); +}; + + +void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2){ + + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x , y); + fprintf(output,"%i %i LT\n", x1 , y); + fprintf(output, "%i %i LT\n", x1 , y2 ); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); +}; + +void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1){ + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x , y); + fprintf(output, "%i %i LT\n", x1 , y ); + fprintf(output, "ELP\n"); + + fprintf(output, "GR\n"); +}; + +void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3){ + fprintf(output, "GS\n"); + + fprintf(output,"BP\n"); + fprintf(output,"%i %i MT\n", x , y); + fprintf(output, "%i %i LT\n", x , y1 ); + fprintf(output, "%i %i LT\n", x2 , y1 ); + fprintf(output , "%i %i LT\n", x2 , y3); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); +}; + +void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2){ + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x , y); + fprintf(output, "%i %i LT\n", x , y1); + fprintf(output, "%i %i LT\n", x2 , y1); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); +}; + +void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1){ + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x , y); + fprintf(output, "%i %i LT\n", x , y1); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); +}; + +void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x0 , y0); + fprintf(output, "%i %i LT\n", x1 , y1); + fprintf(output, "%i %i LT\n", x2 , y2); + fprintf(output, "ECP\n"); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x0 , y0); + fprintf(output, "%i %i LT\n", x1 , y1); + fprintf(output, "%i %i LT\n", x2 , y2); + fprintf(output, "%i %i LT\n", x3 , y3); + fprintf(output, "ECP\n"); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x0 , y0); + fprintf(output,"%i %i LT\n", x1 , y1); + fprintf(output, "%i %i LT\n", x2 , y2); + fprintf(output, "EFP\n"); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + fprintf(output, "GS\n"); + fprintf(output,"BP\n"); + fprintf(output, "%i %i MT\n", x0 , y0 ); + fprintf(output, "%i %i LT\n", x1 , y1 ); + fprintf(output, "%i %i LT\n", x2 , y2 ); + fprintf(output, "%i %i LT\n", x3 , y3 ); + + fprintf(output, "EFP\n"); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::point(int x, int y){ + rectf(x,y,1,1); +} + +static int dashes_flat[5][7]={ +{-1,0,0,0,0,0,0}, +{3,1,-1,0,0,0,0}, +{1,1,-1,0,0,0,0}, +{3,1,1,1,-1,0,0}, +{3,1,1,1,1,1,-1} +}; + + +//yeah, hack... +static double dashes_cap[5][7]={ +{-1,0,0,0,0,0,0}, +{2,2,-1,0,0,0,0}, +{0.01,1.99,-1,0,0,0,0}, +{2,2,0.01,1.99,-1,0,0}, +{2,2,0.01,1.99,0.01,1.99,-1} +}; + + +void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashes){ + //line_styled_=1; + + linewidth_=width; + linestyle_=style; + //dashes_= dashes; + if(dashes){ + if(dashes != linedash_) + strcpy(linedash_,dashes); + + }else + linedash_[0]=0; + char width0 = 0; + if(!width){ + width=1; //for screen drawing compatability + width0=1; + } + + fprintf(output, "%i setlinewidth\n", width); + + if(!style && (!dashes || !(*dashes)) && width0) //system lines + style = FL_CAP_SQUARE; + + int cap = (style &0xf00) >> 8; + if(cap) cap--; + fprintf(output,"%i setlinecap\n", cap); + + int join = (style & 0xf000) >> 12; + + if(join) join--; + fprintf(output,"%i setlinejoin\n", join); + + + fprintf(output, "["); + if(dashes && *dashes){ + while(*dashes){ + fprintf(output, "%i ", *dashes); + dashes++; + } + }else{ + int * ds; + if(style & 0x200){ // round and square caps, dash length need to be adjusted + double *dt = dashes_cap[style & 0xff]; + while (*dt >= 0){ + fprintf(output, "%g ",width * (*dt)); + dt++; + } + }else{ + + ds = dashes_flat[style & 0xff]; + while (*ds >= 0){ + fprintf(output, "%i ",width * (*ds)); + ds++; + } + } + } + fprintf(output, "] 0 setdash\n"); +}; + +static const char *_fontNames[] = { +"Helvetica", +"Helvetica-Bold", +"Helvetica-Oblique", +"Helvetica-BoldOblique", +"Courier", +"Courier-Bold", +"Courier-Oblique", +"Courier-BoldOblique", +"Times", +"Times-Bold", +"Times-Italic", +"Times-BoldItalic", +"Symbol", +"Courier", +"Courier-Bold", +"ZapfDingbats" +}; + +void Fl_PostScript_Graphics_Driver::font(int f, int s) { + if (f >= FL_FREE_FONT) + f = FL_COURIER; + fprintf(output, "/%s SF\n" , _fontNames[f]); + fprintf(output,"%i FS\n", s); + Fl_Display_Device::display_device()->driver()->font(f,s); // Use display fonts for font measurement + font_ = f; size_ = s; +}; + +void Fl_PostScript_Graphics_Driver::color(Fl_Color c) { + //colored_=1; + color_=c; + Fl::get_color(c, cr_, cg_, cb_); + if (cr_==cg_ && cg_==cb_) { + double gray = cr_/255.0; + fprintf(output, "%g GL\n", gray); + + } else { + double fr, fg, fb; + fr = cr_/255.0; + fg = cg_/255.0; + fb = cb_/255.0; + fprintf(output,"%g %g %g SRGB\n", fr , fg , fb); + } +} + +void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) { + //colored_=1; + cr_=r;cg_=g;cb_=b; + if (r==g && g==b) { + double gray = r/255.0; + fprintf(output, "%g GL\n", gray); + } else { + double fr, fg, fb; + fr = r/255.0; + fg = g/255.0; + fb = b/255.0; + fprintf(output, "%g %g %g SRGB\n", fr , fg , fb); + } +} + +void Fl_PostScript_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) +{ + fprintf(output, "GS %d %d translate %d rotate\n", x, y, - angle); + this->transformed_draw(str, n, 0, 0); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y){ + if (!n || !str || !*str)return; + fprintf(output,"%g (", fl_width(str, n)); + int i=1; + for (int j=0;j240){ + fprintf(output, "\\\n"); + i=0; + } + i++; + switch (*str) { + case '(': case ')': case '\\' : + putc('\\' , output); + /* fallthrough */ + default: + putc(*str , output); + } + str++; + } + fprintf(output, ") %g %g show_pos_width\n", x, y); +} + +struct matrix {double a, b, c, d, x, y;}; +extern matrix * fl_matrix; + +void Fl_PostScript_Graphics_Driver::concat(){ + fprintf(output,"[%g %g %g %g %g %g] CT\n", fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); +} + +void Fl_PostScript_Graphics_Driver::reconcat(){ + fprintf(output, "[%g %g %g %g %g %g] RCT\n" , fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); +} + +///////////////// transformed (double) drawings //////////////////////////////// + + +void Fl_PostScript_Graphics_Driver::begin_points(){ + fprintf(output, "GS\n"); + concat(); + + fprintf(output, "BP\n"); + gap_=1; + shape_=POINTS; +}; + +void Fl_PostScript_Graphics_Driver::begin_line(){ + fprintf(output, "GS\n"); + concat(); + fprintf(output, "BP\n"); + gap_=1; + shape_=LINE; +}; + +void Fl_PostScript_Graphics_Driver::begin_loop(){ + fprintf(output, "GS\n"); + concat(); + fprintf(output, "BP\n"); + gap_=1; + shape_=LOOP; +}; + +void Fl_PostScript_Graphics_Driver::begin_polygon(){ + fprintf(output, "GS\n"); + concat(); + fprintf(output, "BP\n"); + gap_=1; + shape_=POLYGON; +}; + +void Fl_PostScript_Graphics_Driver::vertex(double x, double y){ + if(shape_==POINTS){ + fprintf(output,"%g %g MT\n", x , y); + gap_=1; + return; + } + if(gap_){ + fprintf(output,"%g %g MT\n", x , y); + gap_=0; + }else + fprintf(output, "%g %g LT\n", x , y); +}; + +void Fl_PostScript_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){ + if(shape_==NONE) return; + if(gap_) + fprintf(output,"%g %g MT\n", x , y); + else + fprintf(output, "%g %g LT\n", x , y); + gap_=0; + + fprintf(output, "%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); +}; + + +void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){ + if(shape_==NONE){ + fprintf(output, "GS\n"); + concat(); + // fprintf(output, "BP\n"); + fprintf(output,"%g %g %g 0 360 arc\n", x , y , r); + reconcat(); + // fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); + }else + + fprintf(output, "%g %g %g 0 360 arc\n", x , y , r); + +}; + +void Fl_PostScript_Graphics_Driver::arc(double x, double y, double r, double start, double a){ + if(shape_==NONE) return; + gap_=0; + if(start>a) + fprintf(output, "%g %g %g %g %g arc\n", x , y , r , -start, -a); + else + fprintf(output, "%g %g %g %g %g arcn\n", x , y , r , -start, -a); + +}; + +void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { + fprintf(output, "GS\n"); + //fprintf(output, "BP\n"); + begin_line(); + fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); + fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); + arc(0,0,1,a2,a1); + // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2); + fprintf(output, "%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); + fprintf(output, "%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); + end_line(); + + // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h)); + // fprintf(output, "ELP\n"); + // fprintf(output, 2.0/w , 2.0/w , " SC\n"; + // fprintf(output, (-x - w/2.0) , (-y - h/2) , " TR\n"; + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { + + fprintf(output, "GS\n"); + fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); + fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); + begin_polygon(); + vertex(0,0); + arc(0.0,0.0, 1, a2, a1); + end_polygon(); + fprintf(output, "GR\n"); +} + +void Fl_PostScript_Graphics_Driver::end_points(){ + gap_=1; + reconcat(); + fprintf(output, "ELP\n"); //?? + fprintf(output, "GR\n"); + shape_=NONE; +} + +void Fl_PostScript_Graphics_Driver::end_line(){ + gap_=1; + reconcat(); + fprintf(output, "ELP\n"); + fprintf(output, "GR\n"); + shape_=NONE; +} +void Fl_PostScript_Graphics_Driver::end_loop(){ + gap_=1; + reconcat(); + fprintf(output, "ECP\n"); + fprintf(output, "GR\n"); + shape_=NONE; +} + +void Fl_PostScript_Graphics_Driver::end_polygon(){ + + gap_=1; + reconcat(); + fprintf(output, "EFP\n"); + fprintf(output, "GR\n"); + shape_=NONE; +} + +void Fl_PostScript_Graphics_Driver::transformed_vertex(double x, double y){ + reconcat(); + if(gap_){ + fprintf(output, "%g %g MT\n", x , y); + gap_=0; + }else + fprintf(output, "%g %g LT\n", x , y); + concat(); +}; + +///////////////////////////// Clipping ///////////////////////////////////////////// + +void Fl_PostScript_Graphics_Driver::push_clip(int x, int y, int w, int h) { + Clip * c=new Clip(); + clip_box(x,y,w,h,c->x,c->y,c->w,c->h); + c->prev=clip_; + clip_=c; + fprintf(output, "CR\nCS\n"); + if(lang_level_<3) + recover(); + fprintf(output, "%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); + +} + +void Fl_PostScript_Graphics_Driver::push_no_clip() { + Clip * c = new Clip(); + c->prev=clip_; + clip_=c; + clip_->x = clip_->y = clip_->w = clip_->h = -1; + fprintf(output, "CR\nCS\n"); + if(lang_level_<3) + recover(); +} + +void Fl_PostScript_Graphics_Driver::pop_clip() { + if(!clip_)return; + Clip * c=clip_; + clip_=clip_->prev; + delete c; + fprintf(output, "CR\nCS\n"); + if(clip_ && clip_->w >0) + fprintf(output, "%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); + // uh, -0.5 is to match screen clipping, for floats there should be something beter + if(lang_level_<3) + recover(); +} + +int Fl_PostScript_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H){ + if(!clip_){ + X=x;Y=y;W=w;H=h; + return 1; + } + if(clip_->w < 0){ + X=x;Y=y;W=w;H=h; + return 1; + } + int ret=0; + if (x > (X=clip_->x)) {X=x; ret=1;} + if (y > (Y=clip_->y)) {Y=y; ret=1;} + if ((x+w) < (clip_->x+clip_->w)) { + W=x+w-X; + + ret=1; + + }else + W = clip_->x + clip_->w - X; + if(W<0){ + W=0; + return 1; + } + if ((y+h) < (clip_->y+clip_->h)) { + H=y+h-Y; + ret=1; + }else + H = clip_->y + clip_->h - Y; + if(H<0){ + W=0; + H=0; + return 1; + } + return ret; +}; + +int Fl_PostScript_Graphics_Driver::not_clipped(int x, int y, int w, int h){ + if(!clip_) return 1; + if(clip_->w < 0) return 1; + int X, Y, W, H; + clip_box(x, y, w, h, X, Y, W, H); + if(W) return 1; + return 0; +}; + + +void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) // to implement +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + if(left) *left = (int)(ps->left_margin / ps->scale_x + .5); + if(right) *right = (int)(ps->left_margin / ps->scale_x + .5); + if(top) *top = (int)(ps->top_margin / ps->scale_y + .5); + if(bottom) *bottom = (int)(ps->top_margin / ps->scale_y + .5); +} + +int Fl_PostScript_File_Device::printable_rect(int *w, int *h) +//returns 0 iff OK +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + if(w) *w = (int)((ps->pw_ - 2 * ps->left_margin) / ps->scale_x + .5); + if(h) *h = (int)((ps->ph_ - 2 * ps->top_margin) / ps->scale_y + .5); + return 0; +} + +void Fl_PostScript_File_Device::origin(int x, int y) +{ + x_offset = x; + y_offset = y; + Fl_PostScript_Graphics_Driver *ps = driver(); + fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", + ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x, y, ps->angle); +} + +void Fl_PostScript_File_Device::scale (float s_x, float s_y) +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + ps->scale_x = s_x; + ps->scale_y = s_y; + fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %f rotate GS\n", + ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, ps->angle); +} + +void Fl_PostScript_File_Device::rotate (float rot_angle) +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + ps->angle = - rot_angle; + fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", + ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x_offset, y_offset, ps->angle); +} + +void Fl_PostScript_File_Device::translate(int x, int y) +{ + fprintf(driver()->output, "GS %d %d translate GS\n", x, y); +} + +void Fl_PostScript_File_Device::untranslate(void) +{ + fprintf(driver()->output, "GR GR\n"); +} + +int Fl_PostScript_File_Device::start_page (void) +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + ps->page(ps->page_format_); + x_offset = 0; + y_offset = 0; + ps->scale_x = ps->scale_y = 1.; + ps->angle = 0; + fprintf(ps->output, "GR GR GS %d %d translate GS\n", ps->left_margin, ps->top_margin); + return 0; +} + +int Fl_PostScript_File_Device::end_page (void) +{ + return 0; +} + +void Fl_PostScript_File_Device::end_job (void) +// finishes PostScript & closes file +{ + Fl_PostScript_Graphics_Driver *ps = driver(); + if (ps->nPages) { // for eps nPages is 0 so it is fine .... + fprintf(ps->output, "CR\nGR\nGR\nGR\nSP\n restore\n"); + if (!ps->pages_){ + fprintf(ps->output, "%%%%Trailer\n"); + fprintf(ps->output, "%%%%Pages: %i\n" , ps->nPages); + }; + } else + fprintf(ps->output, "GR\n restore\n"); + fputs("%%EOF",ps->output); + ps->reset(); + fflush(ps->output); + if(ferror(ps->output)) { + fl_alert ("Error during PostScript data output."); + } +#if ! (defined(__APPLE__) || defined(WIN32) ) + if (print_pipe) + pclose(ps->output); + else + fclose(ps->output); +#else + fclose(ps->output); +#endif + while (ps->clip_){ + Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_; + ps->clip_= ps->clip_->prev; + delete c; + } + if (ps->close_cmd_) (*ps->close_cmd_)(ps->output); + Fl_Display_Device::display_device()->set_current(); +} + +#if ! (defined(__APPLE__) || defined(WIN32) ) +int Fl_Printer::start_job(int pages, int *firstpage, int *lastpage) { + enum Fl_PostScript_Graphics_Driver::Page_Format format; + enum Fl_PostScript_Graphics_Driver::Page_Layout layout; + + // first test version for print dialog + if (!print_panel) make_print_panel(); + print_load(); + print_selection->deactivate(); + print_all->setonly(); + print_all->do_callback(); + print_from->value("1"); + { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); } + print_panel->show(); // this is modal + while (print_panel->shown()) Fl::wait(); + + if (!print_start) // user clicked cancel + return 1; + + // get options + + format = print_page_size->value() ? Fl_PostScript_Graphics_Driver::A4 : Fl_PostScript_Graphics_Driver::LETTER; + { // page range choice + int from = 1, to = pages; + if (print_pages->value()) { + sscanf(print_from->value(), "%d", &from); + sscanf(print_to->value(), "%d", &to); + } + if (from < 1) from = 1; + if (to > pages) to = pages; + if (to < from) to = from; + if (firstpage) *firstpage = from; + if (lastpage) *lastpage = to; + pages = to - from + 1; + } + + if (print_output_mode[0]->value()) layout = Fl_PostScript_Graphics_Driver::PORTRAIT; + else if (print_output_mode[1]->value()) layout = Fl_PostScript_Graphics_Driver::LANDSCAPE; + else if (print_output_mode[2]->value()) layout = Fl_PostScript_Graphics_Driver::PORTRAIT; + else layout = Fl_PostScript_Graphics_Driver::LANDSCAPE; + + print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe) + + const char *media = print_page_size->text(print_page_size->value()); + const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + if (!print_pipe) printer = ""; + + if (!print_pipe) // fall back to file printing + return Fl_PostScript_File_Device::start_job (pages, format, layout); + + // Print: pipe the output into the lp command... + + char command[1024]; + snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s", + printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5), + "FLTK", media); + + Fl_PostScript_Graphics_Driver *ps = driver(); + ps->output = popen(command, "w"); + if (!ps->output) { + fl_alert("could not run command: %s\n",command); + return 1; + } + this->set_current(); + return ps->start_postscript(pages, format, layout); // start printing +} + +#endif // ! (defined(__APPLE__) || defined(WIN32) ) + +#endif // FL_DOXYGEN + +// +// End of "$Id: Fl_PS_Printer.cxx 7520 2010-04-16 20:19:09Z manolo $". +// diff --git a/src/Fl_Printer.cxx b/src/Fl_Printer.cxx index d6e8425b3..7214ea1b7 100644 --- a/src/Fl_Printer.cxx +++ b/src/Fl_Printer.cxx @@ -34,30 +34,60 @@ #include #endif -#include +#include // print dialog customization strings - +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_title = "Print"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_printer = "Printer:"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_range = "Print Range"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_copies = "Copies"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_all = "All"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_pages = "Pages"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_from = "From:"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_to = "To:"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_properties = "Properties..."; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_copyNo = "# Copies:"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_print_button = "Print"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_cancel_button = "Cancel"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_print_to_file = "Print To File"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::property_title = "Printer Properties"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::property_pagesize = "Page Size:"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::property_mode = "Output Mode:"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::property_use = "Use"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::property_save = "Save"; +/** [this text may be customized at run-time] */ const char *Fl_Printer::property_cancel = "Cancel"; +const char *Fl_Printer::device_type = "Fl_Printer"; + +void Fl_Printer::set_current() +{ +#ifdef __APPLE__ + fl_gc = (CGContextRef)gc; +#elif defined(WIN32) + fl_gc = (HDC)gc; +#endif + this->Fl_Surface_Device::set_current(); +} + // // End of "$Id$". // diff --git a/src/Fl_Quartz_Printer.mm b/src/Fl_Quartz_Printer.mm index 874686d3a..4bd15be58 100644 --- a/src/Fl_Quartz_Printer.mm +++ b/src/Fl_Quartz_Printer.mm @@ -35,15 +35,16 @@ extern void fl_quartz_restore_line_style_(); -Fl_Printer::Fl_Printer(void) +Fl_System_Printer::Fl_System_Printer(void) { x_offset = 0; y_offset = 0; scale_x = scale_y = 1.; - type_ = quartz_printer; + type_ = device_type; + driver(fl_device); } -Fl_Printer::~Fl_Printer(void) {} +Fl_System_Printer::~Fl_System_Printer(void) {} int Fl_Printer::start_job (int pagecount, int *frompage, int *topage) //printing using a Quartz graphics context @@ -288,7 +289,7 @@ void Fl_Printer::end_job (void) fl_alert ("PM Session error %d", (int)status); } PMSessionEndDocumentNoDialog(printSession); - Fl_Device::display_device()->set_current(); + Fl_Display_Device::display_device()->set_current(); fl_gc = 0; Fl::first_window()->show(); } diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index bb7e1e19e..0b09774aa 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -117,9 +117,11 @@ static void createAppleMenu(void); static Fl_Region MacRegionMinusRect(Fl_Region r, int x,int y,int w,int h); static void cocoaMouseHandler(NSEvent *theEvent); -static Fl_Quartz_Display fl_quartz_device; -FL_EXPORT Fl_Display *fl_display_device = (Fl_Display*)&fl_quartz_device; // does not change -FL_EXPORT Fl_Device *fl_device = (Fl_Device*)&fl_quartz_device; // the current target device of graphics operations +static Fl_Quartz_Graphics_Driver fl_quartz_driver; +static Fl_Display_Device fl_quartz_display(&fl_quartz_driver); +FL_EXPORT Fl_Display_Device *fl_display_device = (Fl_Display_Device*)&fl_quartz_display; // does not change +FL_EXPORT Fl_Graphics_Driver *fl_device = (Fl_Graphics_Driver*)&fl_quartz_driver; // the current target device of graphics operations +FL_EXPORT Fl_Surface_Device *fl_surface = (Fl_Surface_Device*)fl_display_device; // the current target surface of graphics operations // public variables int fl_screen; @@ -2963,7 +2965,7 @@ int MACscreen_init(XRectangle screens[]) - (void)printPanel { Fl_Printer printer; - //Fl_PSfile_Device printer; + //Fl_PostScript_File_Device printer; int w, h; Fl_Window *win = Fl::first_window(); if(!win) return; @@ -3466,7 +3468,7 @@ WindowRef MACwindowRef(Fl_Window *w) // so a CGRect matches exactly what is denoted x,y,w,h for clipping purposes CGRect fl_cgrectmake_cocoa(int x, int y, int w, int h) { - if (Fl_Device::current()->type() == Fl_Device::quartz_printer) return CGRectMake(x, y, w-1.5 , h-1.5 ); + if ( Fl_Surface_Device::surface()->type() == Fl_Printer::device_type ) return CGRectMake(x, y, w-1.5 , h-1.5 ); return CGRectMake(x, y, w > 0 ? w - 0.9 : 0, h > 0 ? h - 0.9 : 0); } diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index f26d639db..3ccfd3106 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -95,9 +95,11 @@ for async mode proper operation, not mentioning the side effects... */ -static Fl_GDI_Display fl_gdi_device; -FL_EXPORT Fl_Display *fl_display_device = (Fl_Display*)&fl_gdi_device; // does not change -FL_EXPORT Fl_Device *fl_device = (Fl_Device*)&fl_gdi_device; // the current target device of graphics operations +static Fl_GDI_Graphics_Driver fl_gdi_driver; +static Fl_Display_Device fl_gdi_display(&fl_gdi_driver); +FL_EXPORT Fl_Display_Device *fl_display_device = (Fl_Display_Device*)&fl_gdi_display; // does not change +FL_EXPORT Fl_Graphics_Driver *fl_device = (Fl_Graphics_Driver*)&fl_gdi_driver; // the current target driver of graphics operations +FL_EXPORT Fl_Surface_Device *fl_surface = (Fl_Surface_Device*)fl_display_device; // the current target surface of graphics operations // dynamic wsock dll handling api: #if defined(__CYGWIN__) && !defined(SOCKET) @@ -1925,7 +1927,7 @@ void fl_cleanup_dc_list(void) { // clean up the list } Fl_Region XRectangleRegion(int x, int y, int w, int h) { - if (Fl_Device::current()->type() < 256) return CreateRectRgn(x,y,x+w,y+h); + if (Fl_Surface_Device::surface()->type() == Fl_Display_Device::device_type) return CreateRectRgn(x,y,x+w,y+h); // because rotation may apply, the rectangle becomes a polygon in device coords POINT pt[4] = { {x, y}, {x + w, y}, {x + w, y + h}, {x, y + h} }; LPtoDP(fl_gc, pt, 4); diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 1c81503f8..5b7f2c520 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -51,9 +51,11 @@ # include # include -static Fl_Xlib_Display fl_xlib_device; -FL_EXPORT Fl_Display *fl_display_device = (Fl_Display*)&fl_xlib_device; // does not change -FL_EXPORT Fl_Device *fl_device = (Fl_Device*)&fl_xlib_device; // the current target device of graphics operations +static Fl_Xlib_Graphics_Driver fl_xlib_driver; +static Fl_Display_Device fl_xlib_display(&fl_xlib_driver); +FL_EXPORT Fl_Display_Device *fl_display_device = (Fl_Display_Device*)&fl_xlib_display; // does not change +FL_EXPORT Fl_Graphics_Driver *fl_device = (Fl_Graphics_Driver*)&fl_xlib_driver; // the current target device of graphics operations +FL_EXPORT Fl_Surface_Device *fl_surface = (Fl_Surface_Device*)fl_display_device; // the current target surface of graphics operations //////////////////////////////////////////////////////////////// // interface to poll/select call: @@ -136,9 +138,7 @@ void Fl::add_fd(int n, void (*cb)(int, void*), void* v) { void Fl::remove_fd(int n, int events) { int i,j; -# if !USE_POLL maxfd = -1; // recalculate maxfd on the fly -# endif for (i=j=0; i maxfd) maxfd = fd[i].fd; # endif + if (fd[i].fd > maxfd) maxfd = fd[i].fd; // move it down in the array if necessary: if (jmenu_window() || win->tooltip_window()) { - Atom net_wm_type = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False); - Atom net_wm_type_kind = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_MENU", False); - int ret = XChangeProperty(fl_display, xp->xid, net_wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&net_wm_type_kind, 1); - } - XMapWindow(fl_display, xp->xid); if (showit) { win->set_visible(); diff --git a/src/fl_arc.cxx b/src/fl_arc.cxx index 0ee4269a4..0003319cc 100644 --- a/src/fl_arc.cxx +++ b/src/fl_arc.cxx @@ -43,7 +43,7 @@ static double _fl_hypot(double x, double y) { return sqrt(x*x + y*y); } -void Fl_Device::arc(double x, double y, double r, double start, double end) { +void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end) { // draw start point accurately: diff --git a/src/fl_arci.cxx b/src/fl_arci.cxx index 41f70b542..cd9d8f3df 100644 --- a/src/fl_arci.cxx +++ b/src/fl_arci.cxx @@ -47,7 +47,7 @@ #endif #include -void Fl_Device::arc(int x,int y,int w,int h,double a1,double a2) { +void Fl_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) { if (w <= 0 || h <= 0) return; #if defined(USE_X11) @@ -82,7 +82,7 @@ void Fl_Device::arc(int x,int y,int w,int h,double a1,double a2) { #endif } -void Fl_Device::pie(int x,int y,int w,int h,double a1,double a2) { +void Fl_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) { if (w <= 0 || h <= 0) return; #if defined(USE_X11) diff --git a/src/fl_color.cxx b/src/fl_color.cxx index 735757427..b4cee410b 100644 --- a/src/fl_color.cxx +++ b/src/fl_color.cxx @@ -127,7 +127,7 @@ Fl_XColor fl_xmap[1][256]; /** Current color for drawing operations */ Fl_Color fl_color_; -void Fl_Device::color(Fl_Color i) { +void Fl_Graphics_Driver::color(Fl_Color i) { if (i & 0xffffff00) { unsigned rgb = (unsigned)i; fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); @@ -138,7 +138,7 @@ void Fl_Device::color(Fl_Color i) { } } -void Fl_Device::color(uchar r,uchar g,uchar b) { +void Fl_Graphics_Driver::color(uchar r,uchar g,uchar b) { fl_color_ = fl_rgb_color(r, g, b); if(!fl_gc) return; // don't get a default gc if current window is not yet created/valid XSetForeground(fl_display, fl_gc, fl_xpixel(r,g,b)); diff --git a/src/fl_color_mac.cxx b/src/fl_color_mac.cxx index 6ad4133b0..fa10a2de1 100644 --- a/src/fl_color_mac.cxx +++ b/src/fl_color_mac.cxx @@ -49,7 +49,7 @@ Fl_XMap* fl_current_xmap; Fl_Color fl_color_; -void Fl_Device::color(Fl_Color i) { +void Fl_Graphics_Driver::color(Fl_Color i) { fl_color_ = i; int index; uchar r, g, b; @@ -74,7 +74,7 @@ void Fl_Device::color(Fl_Color i) { CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f); } -void Fl_Device::color(uchar r, uchar g, uchar b) { +void Fl_Graphics_Driver::color(uchar r, uchar g, uchar b) { fl_color_ = fl_rgb_color(r, g, b); float fr = r/255.0f; float fg = g/255.0f; diff --git a/src/fl_color_win32.cxx b/src/fl_color_win32.cxx index f9cd7cc5d..a5b2d6f16 100644 --- a/src/fl_color_win32.cxx +++ b/src/fl_color_win32.cxx @@ -94,7 +94,7 @@ static void set_xmap(Fl_XMap& xmap, COLORREF c) { Fl_Color fl_color_; -void Fl_Device::color(Fl_Color i) { +void Fl_Graphics_Driver::color(Fl_Color i) { if (i & 0xffffff00) { unsigned rgb = (unsigned)i; fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); @@ -118,7 +118,7 @@ void Fl_Device::color(Fl_Color i) { } } -void Fl_Device::color(uchar r, uchar g, uchar b) { +void Fl_Graphics_Driver::color(uchar r, uchar g, uchar b) { static Fl_XMap xmap; COLORREF c = RGB(r,g,b); fl_color_ = fl_rgb_color(r, g, b); diff --git a/src/fl_curve.cxx b/src/fl_curve.cxx index d9406787e..efacbd677 100644 --- a/src/fl_curve.cxx +++ b/src/fl_curve.cxx @@ -38,7 +38,7 @@ #include #include -void Fl_Device::curve(double X0, double Y0, +void Fl_Graphics_Driver::curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3) { diff --git a/src/fl_draw_image.cxx b/src/fl_draw_image.cxx index 9542a9f0a..aa0c09e54 100644 --- a/src/fl_draw_image.cxx +++ b/src/fl_draw_image.cxx @@ -543,17 +543,17 @@ static void innards(const uchar *buf, int X, int Y, int W, int H, } } -void Fl_Device::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ +void Fl_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0); } -void Fl_Device::draw_image(Fl_Draw_Image_Cb cb, void* data, +void Fl_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data); } -void Fl_Device::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ +void Fl_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ innards(buf,x,y,w,h,d,l,1,0,0); } -void Fl_Device::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, +void Fl_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x,y,w,h,d,0,1,cb,data); } diff --git a/src/fl_draw_image_mac.cxx b/src/fl_draw_image_mac.cxx index a7c14fa9e..6f781d2a5 100644 --- a/src/fl_draw_image_mac.cxx +++ b/src/fl_draw_image_mac.cxx @@ -148,17 +148,17 @@ static void innards(const uchar *buf, int X, int Y, int W, int H, CGContextSetShouldAntialias(fl_gc, true); } -void Fl_Device::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ +void Fl_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0); } -void Fl_Device::draw_image(Fl_Draw_Image_Cb cb, void* data, +void Fl_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data); } -void Fl_Device::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ +void Fl_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ innards(buf,x,y,w,h,d,l,1,0,0); } -void Fl_Device::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, +void Fl_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x,y,w,h,d,0,1,cb,data); } diff --git a/src/fl_draw_image_win32.cxx b/src/fl_draw_image_win32.cxx index 403dfd9fe..e1d970ad7 100644 --- a/src/fl_draw_image_win32.cxx +++ b/src/fl_draw_image_win32.cxx @@ -46,6 +46,7 @@ #include #include +#include #include #include @@ -254,7 +255,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H, } } } - if(Fl_Device::current()->type() == Fl_Device::gdi_printer) { + if(Fl_Surface_Device::surface()->type() == Fl_Printer::device_type) { // if print context, device and logical units are not equal, so SetDIBitsToDevice // does not do the expected job, whereas StretchDIBits does it. StretchDIBits(fl_gc, x, y+j-k, w, k, 0, 0, w, k, @@ -283,7 +284,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H, static int fl_abs(int v) { return v<0 ? -v : v; } -void Fl_Device::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ +void Fl_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; innards(buf,x,y,w,h,d,l,fl_abs(d),0,0); @@ -292,7 +293,7 @@ void Fl_Device::draw_image(const uchar* buf, int x, int y, int w, int h, int d, } } -void Fl_Device::draw_image(Fl_Draw_Image_Cb cb, void* data, +void Fl_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; @@ -302,7 +303,7 @@ void Fl_Device::draw_image(Fl_Draw_Image_Cb cb, void* data, } } -void Fl_Device::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ +void Fl_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; innards(buf,x,y,w,h,d,l,1,0,0); @@ -311,7 +312,7 @@ void Fl_Device::draw_image_mono(const uchar* buf, int x, int y, int w, int h, in } } -void Fl_Device::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, +void Fl_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; diff --git a/src/fl_draw_pixmap.cxx b/src/fl_draw_pixmap.cxx index 5df23a3a6..a8755938a 100644 --- a/src/fl_draw_pixmap.cxx +++ b/src/fl_draw_pixmap.cxx @@ -40,6 +40,9 @@ #include #include #include "flstring.h" +#ifdef __APPLE_QUARTZ__ +#include +#endif static int ncolors, chars_per_pixel; @@ -139,8 +142,6 @@ struct pixmap_data { }; }; -# ifndef __APPLE_QUARTZ__ - // callback for 1 byte per pixel: static void cb1(void*v, int x, int y, int w, uchar* buf) { pixmap_data& d = *(pixmap_data*)v; @@ -160,8 +161,6 @@ static void cb2(void*v, int x, int y, int w, uchar* buf) { } } -# endif // !__APPLE_QUARTZ__ - #endif // U64 else U32 uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here @@ -222,7 +221,7 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { if (!fl_measure_pixmap(cdata, d.w, d.h)) return 0; const uchar*const* data = (const uchar*const*)(cdata+1); int transparent_index = -1; - uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color + uchar *transparent_c; // such that transparent_c[0,1,2] are the RGB of the transparent color #ifdef WIN32 color_count = 0; used_colors = (uchar *)malloc(abs(ncolors)*3*sizeof(uchar)); @@ -335,15 +334,43 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { } d.data = data; #ifdef WIN32 - if (transparent_c) { make_unused_color(transparent_c[0], transparent_c[1], transparent_c[2]); +#endif + +#ifdef __APPLE_QUARTZ__ + if (fl_surface->type() == Fl_Printer::device_type) { + bool transparent = (transparent_index>=0); + transparent = true; + U32 *array = new U32[d.w * d.h], *q = array; + for (int Y = 0; Y < d.h; Y++) { + const uchar* p = data[Y]; + if (chars_per_pixel <= 1) { + for (int X = 0; X < d.w; X++) { + *q++ = d.colors[*p++]; + } + } else { + for (int X = 0; X < d.w; X++) { + U32* colors = (U32*)d.byte1[*p++]; + *q++ = colors[*p++]; + } + } } - else { - uchar r, g, b; - make_unused_color(r, g, b); + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, d.w * d.h * 4, 0L); + CGImageRef img = CGImageCreate(d.w, d.h, 8, 4*8, 4*d.w, + lut, transparent?kCGImageAlphaLast:kCGImageAlphaNoneSkipLast, + src, 0L, false, kCGRenderingIntentDefault); + CGColorSpaceRelease(lut); + CGDataProviderRelease(src); + CGRect rect = { { x, y} , { d.w, d.h } }; + Fl_X::q_begin_image(rect, 0, 0, d.w, d.h); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CGImageRelease(img); + delete array; } -#endif -#ifndef __APPLE_QUARTZ__ + else { +#endif // __APPLE_QUARTZ__ // build the mask bitmap used by Fl_Pixmap: if (fl_mask_bitmap && transparent_index >= 0) { @@ -386,40 +413,9 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { } fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4); - -#else // __APPLE_QUARTZ__ - - bool transparent = (transparent_index>=0); - transparent = true; - U32 *array = new U32[d.w * d.h], *q = array; - for (int Y = 0; Y < d.h; Y++) { - const uchar* p = data[Y]; - if (chars_per_pixel <= 1) { - for (int X = 0; X < d.w; X++) { - *q++ = d.colors[*p++]; - } - } else { - for (int X = 0; X < d.w; X++) { - U32* colors = (U32*)d.byte1[*p++]; - *q++ = colors[*p++]; - } +#ifdef __APPLE_QUARTZ__ } - } - CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); - CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, d.w * d.h * 4, 0L); - CGImageRef img = CGImageCreate(d.w, d.h, 8, 4*8, 4*d.w, - lut, transparent?kCGImageAlphaLast:kCGImageAlphaNoneSkipLast, - src, 0L, false, kCGRenderingIntentDefault); - CGColorSpaceRelease(lut); - CGDataProviderRelease(src); - CGRect rect = { { x, y} , { d.w, d.h } }; - Fl_X::q_begin_image(rect, 0, 0, d.w, d.h); - CGContextDrawImage(fl_gc, rect, img); - Fl_X::q_end_image(); - CGImageRelease(img); - delete array; - -#endif // !__APPLE_QUARTZ__ +#endif if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i]; return 1; diff --git a/src/fl_font_mac.cxx b/src/fl_font_mac.cxx index 92fd58055..cb6887827 100644 --- a/src/fl_font_mac.cxx +++ b/src/fl_font_mac.cxx @@ -239,7 +239,7 @@ Fl_Font fl_font_ = 0; Fl_Fontsize fl_size_ = 0; -void Fl_Device::font(Fl_Font fnum, Fl_Fontsize size) { +void Fl_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { if (fnum==-1) { fl_font_ = 0; fl_size_ = 0; @@ -402,7 +402,7 @@ void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) { void fl_draw(const char *str, int n, float x, float y); -void Fl_Device::draw(const char* str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(const char* str, int n, int x, int y) { fl_draw(str, n, (float)x-0.0f, (float)y+0.5f); } @@ -480,7 +480,7 @@ void fl_draw(const char *str, int n, float x, float y) { #endif } -void Fl_Device::draw(int angle, const char *str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { CGContextSaveGState(fl_gc); CGContextTranslateCTM(fl_gc, x, y); CGContextRotateCTM(fl_gc, - angle*(M_PI/180) ); diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx index fd0e3fdbf..7220eb3b9 100644 --- a/src/fl_font_win32.cxx +++ b/src/fl_font_win32.cxx @@ -24,6 +24,9 @@ // // http://www.fltk.org/str.php // + +#include + static int fl_angle_ = 0; #ifndef FL_DOXYGEN @@ -143,7 +146,7 @@ void fl_font(Fl_Font fnum, Fl_Fontsize size, int angle) { fl_fontsize = find(fnum, size, angle); } -void Fl_Device::font(Fl_Font fnum, Fl_Fontsize size) { +void Fl_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { fl_font(fnum, size, 0); } @@ -247,7 +250,7 @@ static void on_printer_extents_update(int &dx, int &dy, int &w, int &h) // if printer context, extents shd be converted to logical coords #define EXTENTS_UPDATE(x,y,w,h) \ - if (Fl_Device::current()->type() == Fl_Device::gdi_printer) { on_printer_extents_update(x,y,w,h); } + if (Fl_Surface_Device::surface()->type() == Fl_Printer::device_type) { on_printer_extents_update(x,y,w,h); } static unsigned short *ext_buff = NULL; // UTF-16 converted version of input UTF-8 string static unsigned wc_len = 0; // current string buffer dimension @@ -331,7 +334,7 @@ exit_error: return; } // fl_text_extents -void Fl_Device::draw(const char* str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(const char* str, int n, int x, int y) { int i = 0; int lx = 0; char *end = (char *)&str[n]; @@ -359,7 +362,7 @@ void Fl_Device::draw(const char* str, int n, int x, int y) { SetTextColor(fl_gc, oldColor); } -void Fl_Device::draw(int angle, const char* str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) { fl_font(fl_font_, fl_size_, angle); // fl_draw(str, n, (int)x, (int)y); int i = 0, i2=0; diff --git a/src/fl_font_x.cxx b/src/fl_font_x.cxx index 1e019f557..e6ccea79c 100644 --- a/src/fl_font_x.cxx +++ b/src/fl_font_x.cxx @@ -269,7 +269,7 @@ XFontStruct* Fl_XFont_On_Demand::value() { return ptr; } -void Fl_Device::font(Fl_Font fnum, Fl_Fontsize size) { +void Fl_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { if (fnum==-1) { fl_font_ = 0; fl_size_ = 0; return; @@ -318,7 +318,7 @@ void fl_text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) { } // fl_text_extents -void Fl_Device::draw(const char* c, int n, int x, int y) { +void Fl_Graphics_Driver::draw(const char* c, int n, int x, int y) { if (font_gc != fl_gc) { if (!current_font) fl_font(FL_HELVETICA, 14); font_gc = fl_gc; @@ -327,7 +327,7 @@ void Fl_Device::draw(const char* c, int n, int x, int y) { // XDrawString(fl_display, fl_window, fl_gc, x, y, c, n); XUtf8DrawString(fl_display, fl_window, current_font, fl_gc, x, y, c, n); } -void Fl_Device::draw(int angle, const char *str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { fprintf(stderr,"ROTATING TEXT NOT IMPLIMENTED\n"); fl_draw(str, n, (int)x, (int)y); } diff --git a/src/fl_font_xft.cxx b/src/fl_font_xft.cxx index 4d7063f80..bf2ca3ee8 100644 --- a/src/fl_font_xft.cxx +++ b/src/fl_font_xft.cxx @@ -133,7 +133,7 @@ void fl_font(Fl_Font fnum, Fl_Fontsize size, int angle) { fl_xftfont = (void*)f->font; } -void Fl_Device::font(Fl_Font fnum, Fl_Fontsize size) { +void Fl_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { fl_font(fnum,size,0); } @@ -502,7 +502,7 @@ void fl_destroy_xft_draw(Window id) { #endif } -void Fl_Device::draw(const char *str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(const char *str, int n, int x, int y) { if ( !current_font ) { fl_font(FL_HELVETICA, 14); } @@ -539,7 +539,7 @@ void Fl_Device::draw(const char *str, int n, int x, int y) { XftDrawStringUtf8(draw_, &color, current_font, x, y, (XftChar8 *)str, n); } -void Fl_Device::draw(int angle, const char *str, int n, int x, int y) { +void Fl_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { fl_font(fl_font_, fl_size_, angle); fl_draw(str, n, (int)x, (int)y); fl_font(fl_font_, fl_size_); diff --git a/src/fl_line_style.cxx b/src/fl_line_style.cxx index b2bf1fc12..2fed71480 100644 --- a/src/fl_line_style.cxx +++ b/src/fl_line_style.cxx @@ -33,8 +33,10 @@ #include #include #include +#include #include "flstring.h" #include +#include //TMP #ifdef __APPLE_QUARTZ__ float fl_quartz_line_width_ = 1.0f; @@ -50,7 +52,7 @@ void fl_quartz_restore_line_style_() { } #endif -void Fl_Device::line_style(int style, int width, char* dashes) { +void Fl_Graphics_Driver::line_style(int style, int width, char* dashes) { #if defined(USE_X11) int ndashes = dashes ? strlen(dashes) : 0; @@ -117,7 +119,7 @@ void Fl_Device::line_style(int style, int width, char* dashes) { fl_quartz_line_width_ = (float)width; fl_quartz_line_cap_ = Cap[(style>>8)&3]; // when printing kCGLineCapSquare seems better for solid lines - if (Fl_Device::current()->type() == quartz_printer && style == FL_SOLID && dashes == NULL) { + if ( Fl_Surface_Device::surface()->type() == Fl_Printer::device_type && style == FL_SOLID && dashes == NULL ) { fl_quartz_line_cap_ = kCGLineCapSquare; } fl_quartz_line_join_ = Join[(style>>12)&3]; diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx index df8cbef9a..5f12936d9 100644 --- a/src/fl_rect.cxx +++ b/src/fl_rect.cxx @@ -38,15 +38,16 @@ #include #include #include +#include #include #include #ifdef __APPLE_QUARTZ__ extern float fl_quartz_line_width_; -#define USINGQUARTZPRINTER (Fl_Device::current()->type() == quartz_printer) +#define USINGQUARTZPRINTER (Fl_Surface_Device::surface()->type() == Fl_Printer::device_type) #endif -void Fl_Device::rect(int x, int y, int w, int h) { +void Fl_Graphics_Driver::rect(int x, int y, int w, int h) { if (w<=0 || h<=0) return; #if defined(USE_X11) @@ -67,7 +68,7 @@ void Fl_Device::rect(int x, int y, int w, int h) { #endif } -void Fl_Device::rectf(int x, int y, int w, int h) { +void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) { if (w<=0 || h<=0) return; #if defined(USE_X11) if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h); @@ -86,7 +87,7 @@ void Fl_Device::rectf(int x, int y, int w, int h) { #endif } -void Fl_Device::xyline(int x, int y, int x1) { +void Fl_Graphics_Driver::xyline(int x, int y, int x1) { #if defined(USE_X11) XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y); #elif defined(WIN32) @@ -102,7 +103,7 @@ void Fl_Device::xyline(int x, int y, int x1) { #endif } -void Fl_Device::xyline(int x, int y, int x1, int y2) { +void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) { #if defined (USE_X11) XPoint p[3]; p[0].x = x; p[0].y = p[1].y = y; @@ -126,7 +127,7 @@ void Fl_Device::xyline(int x, int y, int x1, int y2) { #endif } -void Fl_Device::xyline(int x, int y, int x1, int y2, int x3) { +void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { #if defined(USE_X11) XPoint p[4]; p[0].x = x; p[0].y = p[1].y = y; @@ -153,7 +154,7 @@ void Fl_Device::xyline(int x, int y, int x1, int y2, int x3) { #endif } -void Fl_Device::yxline(int x, int y, int y1) { +void Fl_Graphics_Driver::yxline(int x, int y, int y1) { #if defined(USE_X11) XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1); #elif defined(WIN32) @@ -171,7 +172,7 @@ void Fl_Device::yxline(int x, int y, int y1) { #endif } -void Fl_Device::yxline(int x, int y, int y1, int x2) { +void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) { #if defined(USE_X11) XPoint p[3]; p[0].x = p[1].x = x; p[0].y = y; @@ -195,7 +196,7 @@ void Fl_Device::yxline(int x, int y, int y1, int x2) { #endif } -void Fl_Device::yxline(int x, int y, int y1, int x2, int y3) { +void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { #if defined(USE_X11) XPoint p[4]; p[0].x = p[1].x = x; p[0].y = y; @@ -222,7 +223,7 @@ void Fl_Device::yxline(int x, int y, int y1, int x2, int y3) { #endif } -void Fl_Device::line(int x, int y, int x1, int y1) { +void Fl_Graphics_Driver::line(int x, int y, int x1, int y1) { #if defined(USE_X11) XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1); #elif defined(WIN32) @@ -242,7 +243,7 @@ void Fl_Device::line(int x, int y, int x1, int y1) { #endif } -void Fl_Device::line(int x, int y, int x1, int y1, int x2, int y2) { +void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { #if defined(USE_X11) XPoint p[3]; p[0].x = x; p[0].y = y; @@ -268,7 +269,7 @@ void Fl_Device::line(int x, int y, int x1, int y1, int x2, int y2) { #endif } -void Fl_Device::loop(int x, int y, int x1, int y1, int x2, int y2) { +void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) { #if defined(USE_X11) XPoint p[4]; p[0].x = x; p[0].y = y; @@ -294,7 +295,7 @@ void Fl_Device::loop(int x, int y, int x1, int y1, int x2, int y2) { #endif } -void Fl_Device::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { +void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { #if defined(USE_X11) XPoint p[5]; p[0].x = x; p[0].y = y; @@ -323,7 +324,7 @@ void Fl_Device::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y #endif } -void Fl_Device::polygon(int x, int y, int x1, int y1, int x2, int y2) { +void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) { XPoint p[4]; p[0].x = x; p[0].y = y; p[1].x = x1; p[1].y = y1; @@ -348,7 +349,7 @@ void Fl_Device::polygon(int x, int y, int x1, int y1, int x2, int y2) { #endif } -void Fl_Device::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { +void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { XPoint p[5]; p[0].x = x; p[0].y = y; p[1].x = x1; p[1].y = y1; @@ -375,7 +376,7 @@ void Fl_Device::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, in #endif } -void Fl_Device::point(int x, int y) { +void Fl_Graphics_Driver::point(int x, int y) { #if defined(USE_X11) XDrawPoint(fl_display, fl_window, fl_gc, x, y); #elif defined(WIN32) @@ -450,7 +451,7 @@ Fl_Region fl_clip_region() { return rstack[rstackptr]; } -void Fl_Device::push_clip(int x, int y, int w, int h) { +void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) { Fl_Region r; if (w > 0 && h > 0) { r = XRectangleRegion(x,y,w,h); @@ -487,14 +488,14 @@ void Fl_Device::push_clip(int x, int y, int w, int h) { } // make there be no clip (used by fl_begin_offscreen() only!) -void Fl_Device::push_no_clip() { +void Fl_Graphics_Driver::push_no_clip() { if (rstackptr < STACK_MAX) rstack[++rstackptr] = 0; else Fl::warning("fl_push_no_clip: clip stack overflow!\n"); fl_restore_clip(); } // pop back to previous clip: -void Fl_Device::pop_clip() { +void Fl_Graphics_Driver::pop_clip() { if (rstackptr > 0) { Fl_Region oldr = rstack[rstackptr--]; if (oldr) XDestroyRegion(oldr); @@ -502,7 +503,7 @@ void Fl_Device::pop_clip() { fl_restore_clip(); } -int Fl_Device::not_clipped(int x, int y, int w, int h) { +int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (x+w <= 0 || y+h <= 0) return 0; Fl_Region r = rstack[rstackptr]; #if defined (USE_X11) @@ -510,7 +511,7 @@ int Fl_Device::not_clipped(int x, int y, int w, int h) { #elif defined(WIN32) if (!r) return 1; RECT rect; - if (Fl_Device::current()->type() == Fl_Device::gdi_printer) { // in case of print context, convert coords from logical to device + if (Fl_Surface_Device::surface()->type() == Fl_Printer::device_type) { // in case of print context, convert coords from logical to device POINT pt[2] = { {x, y}, {x + w, y + h} }; LPtoDP(fl_gc, pt, 2); rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y; @@ -533,7 +534,7 @@ int Fl_Device::not_clipped(int x, int y, int w, int h) { } // return rectangle surrounding intersection of this rectangle and clip: -int Fl_Device::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ +int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ X = x; Y = y; W = w; H = h; Fl_Region r = rstack[rstackptr]; if (!r) return 0; @@ -572,7 +573,7 @@ int Fl_Device::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& } else { // partial intersection RECT rect; GetRgnBox(temp, &rect); - if(Fl_Device::current()->type() == Fl_Device::gdi_printer) { // if print context, convert coords from device to logical + if(Fl_Surface_Device::surface()->type() == Fl_Printer::device_type) { // if print context, convert coords from device to logical POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} }; DPtoLP(fl_gc, pt, 2); X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y; diff --git a/src/fl_vertex.cxx b/src/fl_vertex.cxx index 014593dab..f62a8a263 100644 --- a/src/fl_vertex.cxx +++ b/src/fl_vertex.cxx @@ -145,13 +145,13 @@ static int n; static int what; enum {LINE, LOOP, POLYGON, POINT_}; -void Fl_Device::begin_points() {n = 0; what = POINT_;} +void Fl_Graphics_Driver::begin_points() {n = 0; what = POINT_;} -void Fl_Device::begin_line() {n = 0; what = LINE;} +void Fl_Graphics_Driver::begin_line() {n = 0; what = LINE;} -void Fl_Device::begin_loop() {n = 0; what = LOOP;} +void Fl_Graphics_Driver::begin_loop() {n = 0; what = LOOP;} -void Fl_Device::begin_polygon() {n = 0; what = POLYGON;} +void Fl_Graphics_Driver::begin_polygon() {n = 0; what = POLYGON;} /** Transforms coordinate using the current transformation matrix. @@ -189,7 +189,7 @@ static void fl_transformed_vertex(COORD_T x, COORD_T y) { } } -void Fl_Device::transformed_vertex(double xf, double yf) { +void Fl_Graphics_Driver::transformed_vertex(double xf, double yf) { #ifdef __APPLE_QUARTZ__ fl_transformed_vertex(COORD_T(xf), COORD_T(yf)); #else @@ -197,11 +197,11 @@ void Fl_Device::transformed_vertex(double xf, double yf) { #endif } -void Fl_Device::vertex(double x,double y) { +void Fl_Graphics_Driver::vertex(double x,double y) { fl_transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y); } -void Fl_Device::end_points() { +void Fl_Graphics_Driver::end_points() { #if defined(USE_X11) if (n>1) XDrawPoints(fl_display, fl_window, fl_gc, p, n, 0); #elif defined(WIN32) @@ -219,7 +219,7 @@ void Fl_Device::end_points() { #endif } -void Fl_Device::end_line() { +void Fl_Graphics_Driver::end_line() { if (n < 2) { fl_end_points(); return; @@ -245,13 +245,13 @@ static void fixloop() { // remove equal points from closed path while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--; } -void Fl_Device::end_loop() { +void Fl_Graphics_Driver::end_loop() { fixloop(); if (n>2) fl_transformed_vertex((COORD_T)p[0].x, (COORD_T)p[0].y); fl_end_line(); } -void Fl_Device::end_polygon() { +void Fl_Graphics_Driver::end_polygon() { fixloop(); if (n < 3) { fl_end_line(); @@ -284,7 +284,7 @@ static int counts[20]; static int numcount; #endif -void Fl_Device::begin_complex_polygon() { +void Fl_Graphics_Driver::begin_complex_polygon() { fl_begin_polygon(); gap_ = 0; #if defined(WIN32) @@ -292,7 +292,7 @@ void Fl_Device::begin_complex_polygon() { #endif } -void Fl_Device::gap() { +void Fl_Graphics_Driver::gap() { while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--; if (n > gap_+2) { fl_transformed_vertex((COORD_T)p[gap_].x, (COORD_T)p[gap_].y); @@ -305,7 +305,7 @@ void Fl_Device::gap() { } } -void Fl_Device::end_complex_polygon() { +void Fl_Graphics_Driver::end_complex_polygon() { fl_gap(); if (n < 3) { fl_end_line(); @@ -336,7 +336,7 @@ void Fl_Device::end_complex_polygon() { // warning: these do not draw rotated ellipses correctly! // See fl_arc.c for portable version. -void Fl_Device::circle(double x, double y,double r) { +void Fl_Graphics_Driver::circle(double x, double y,double r) { double xt = fl_transform_x(x,y); double yt = fl_transform_y(x,y); double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); diff --git a/src/ps_image.cxx b/src/ps_image.cxx index 7958d2957..fa4a6fe2c 100644 --- a/src/ps_image.cxx +++ b/src/ps_image.cxx @@ -20,9 +20,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // -// Please report all bugs and problems on the following page: -// -// http://www.fltk.org/str.php +// Please report all bugs and problems to "fltk-bugs@fltk.org". // #ifndef FL_DOXYGEN @@ -31,12 +29,12 @@ #include #include -#include +#include #include #include #include -int Fl_PSfile_Device::alpha_mask(const uchar * data, int w, int h, int D, int LD){ +int Fl_PostScript_Graphics_Driver::alpha_mask(const uchar * data, int w, int h, int D, int LD){ mask = 0; if((D/2)*2 != D){ //no mask info @@ -184,18 +182,27 @@ int Fl_PSfile_Device::alpha_mask(const uchar * data, int w, int h, int D, int LD return 0; } -// bitwise inversion of all 4-bit quantities -static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; -// bitwise inversion of a byte -static inline uchar swap_byte(const uchar b){ - return (swapped[b & 0xF] << 4) | swapped[b >> 4]; - } + +// TODO: anybody has more efficient algoritm? +static inline uchar swap_byte(const uchar i){ + uchar b =0; + if(i & 1) b |= 128; + if(i & 2) b |= 64; + if(i & 4) b |= 32; + if(i & 8) b |= 16; + if(i & 16) b |= 8; + if(i & 32) b |= 4; + if(i & 64) b |= 2; + if(i & 128) b |= 1; + return b; +} + extern uchar **fl_mask_bitmap; -void Fl_PSfile_Device::draw_scaled_image(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D, int LD) { +void Fl_PostScript_Graphics_Driver::draw_scaled_image(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D, int LD) { if(D<3){ //mono @@ -262,7 +269,7 @@ void Fl_PSfile_Device::draw_scaled_image(const uchar *data, double x, double y, }; -void Fl_PSfile_Device::draw_scaled_image(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D) { +void Fl_PostScript_Graphics_Driver::draw_scaled_image(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D) { int level2_mask = 0; fprintf(output,"save\n"); @@ -350,7 +357,7 @@ void Fl_PSfile_Device::draw_scaled_image(Fl_Draw_Image_Cb call, void *data, doub delete[] rgbdata; } -void Fl_PSfile_Device::draw_scaled_image_mono(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D, int LD) { +void Fl_PostScript_Graphics_Driver::draw_scaled_image_mono(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D, int LD) { fprintf(output,"save\n"); @@ -411,7 +418,7 @@ void Fl_PSfile_Device::draw_scaled_image_mono(const uchar *data, double x, doubl -void Fl_PSfile_Device::draw_scaled_image_mono(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D) { +void Fl_PostScript_Graphics_Driver::draw_scaled_image_mono(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D) { fprintf(output,"save\n"); int i,j,k; @@ -460,7 +467,7 @@ void Fl_PSfile_Device::draw_scaled_image_mono(Fl_Draw_Image_Cb call, void *data, ////////////////////////////// Image classes ////////////////////// -void Fl_PSfile_Device::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy){ +void Fl_PostScript_Graphics_Driver::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy){ const char * const * di =pxm->data(); int w,h; if (!fl_measure_pixmap(di, w, h)) return; @@ -476,7 +483,7 @@ void Fl_PSfile_Device::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int fl_mask_bitmap=0; }; -void Fl_PSfile_Device::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy){ +void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy){ const uchar * di = rgb->array; int w = rgb->w(); int h = rgb->h(); @@ -490,7 +497,7 @@ void Fl_PSfile_Device::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, i mask=0; }; -void Fl_PSfile_Device::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy){ +void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy){ const uchar * di = bitmap->array; int w,h; int LD=(bitmap->w()+7)/8; -- cgit v1.2.3