[master] 1fbcae1 - Create class Fl_Cairo_Graphics_Driver.

GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 1fbcae1 - Create class Fl_Cairo_Graphics_Driver. "ManoloFLTK" 06:17 Mar 15 top right image
 
commit 1fbcae13bdd0d7cbca12baaadc2a10864ea1aeb6
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Mon Mar 15 14:09:40 2021 +0100
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Mon Mar 15 14:09:50 2021 +0100

    Create class Fl_Cairo_Graphics_Driver.
    
    That class is extracted from inside Fl_PostScript_Graphics_Driver and might
    become handy in the future.

 src/CMakeLists.txt                                 |   3 +
 src/Makefile                                       |   4 +-
 src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H       | 140 +++++
 src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx     | 656 +++++++++++++++++++++
 src/drivers/PostScript/Fl_PostScript.cxx           | 446 +-------------
 .../PostScript/Fl_PostScript_Graphics_Driver.H     |  64 +-
 src/drivers/PostScript/Fl_PostScript_image.cxx     | 139 -----
 7 files changed, 849 insertions(+), 603 deletions(-)

diff --git src/CMakeLists.txt src/CMakeLists.txt
index 7c64a3a..1a614be 100644
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -217,6 +217,9 @@ if (USE_X11)
     set (DRIVER_FILES ${DRIVER_FILES}
       drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
     )
+    if (USE_PANGO)
+      set (DRIVER_FILES ${DRIVER_FILES} drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx)
+    endif (USE_PANGO)
   else ()
     set (DRIVER_FILES ${DRIVER_FILES}
       drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
diff --git src/Makefile src/Makefile
index 00e02c0..1415be1 100644
--- src/Makefile
+++ src/Makefile
@@ -283,7 +283,8 @@ XLIBFONTFILES = \
 
 # These C++ files are used under condition: BUILD_X11 AND BUILD_XFT
 XLIBXFTFILES = \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx \
+	drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
 
 # These C++ files are used under condition: BUILD_GDI
 GDICPPFILES = \
@@ -601,6 +602,7 @@ rebuild:
 
 clean:
 	-$(RM)	*.o xutf8/*.o *.dll.a core.* *~ *.bak *.bck
+	-$(RM)	drivers/Cairo/*.o
 	-$(RM)	drivers/Cocoa/*.o
 	-$(RM)	drivers/Darwin/*.o
 	-$(RM)	drivers/GDI/*.o
diff --git src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
new file mode 100644
index 0000000..bbcb414
--- /dev/null
+++ src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
@@ -0,0 +1,140 @@
+//
+// Support for Cairo graphics for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2021 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file.  If this
+// file is missing or damaged, see the license at:
+//
+//     https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+//     https://www.fltk.org/bugs.php
+//
+
+/* \file
+    Declaration of class Fl_Cairo_Graphics_Driver.
+*/
+
+#include <FL/Fl_Graphics_Driver.H>
+
+typedef struct _cairo cairo_t;
+typedef struct _PangoLayout  PangoLayout;
+typedef struct _PangoFontDescription PangoFontDescription;
+
+class FL_EXPORT Fl_Cairo_Graphics_Driver : public Fl_Graphics_Driver {
+protected:
+  cairo_t *cairo_;
+  PangoLayout *pango_layout_;
+  void draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy);
+public:
+  Fl_Cairo_Graphics_Driver();
+  virtual ~Fl_Cairo_Graphics_Driver();
+  enum SHAPE {NONE=0, LINE, LOOP, POLYGON, POINTS};
+
+  class Clip {
+  public:
+    int x, y, w, h;
+    Clip *prev;
+  };
+  Clip * clip_;
+
+  int lang_level_;
+  int gap_;
+  int pages_;
+  cairo_t *cr() { return cairo_; }
+  PangoLayout *pango_layout() {return pango_layout_;};
+  virtual PangoFontDescription* pango_font_description(Fl_Font fnum) { return NULL; }
+
+  void check_status(void);
+
+  enum SHAPE shape_;
+  int linewidth_;// need for clipping, lang level 1-2
+  int linestyle_;//
+  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();
+
+  float scale_x;
+  float scale_y;
+  float angle;
+  int left_margin;
+  int top_margin;
+
+  double pw_, ph_;
+
+  uchar bg_r, bg_g, bg_b;
+  void transformed_draw(const char* s, int n, double x, double y); //precise text placing
+
+  // implementation of drawing methods
+  void color(Fl_Color c);
+  void color(uchar r, uchar g, uchar b);
+  Fl_Color color();
+
+  void push_clip(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 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 draw_image_mono(const uchar* d, int x,int y,int w,int h, int delta=1, int ld=0);
+  void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3);
+  void draw_image_mono(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=1);
+
+  void draw(const char* s, int nBytes, int x, int y) {transformed_draw(s,nBytes,x,y); };
+  void draw(const char* s, int nBytes, float x, float y) {transformed_draw(s,nBytes,x,y); };
+  void draw(int angle, const char *str, int n, int x, int y);
+  void rtl_draw(const char* s, int n, int x, int y);
+  void draw_pixmap(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy);
+  void draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy);
+  // ---
+  Fl_Bitmask create_bitmask(int w, int h, const uchar *array) { return 0L; }
+
+  void ps_origin(int x, int y);
+  void ps_translate(int, int);
+  void ps_untranslate();
+};
diff --git src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
new file mode 100644
index 0000000..ff64bfe
--- /dev/null
+++ src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
@@ -0,0 +1,656 @@
+//
+// Support for Cairo graphics for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2021 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file.  If this
+// file is missing or damaged, see the license at:
+//
+//     https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+//     https://www.fltk.org/bugs.php
+//
+
+/* \file
+    Implementation of class Fl_Cairo_Graphics_Driver .
+*/
+
+#include <config.h>
+#if USE_PANGO
+
+#include "Fl_Cairo_Graphics_Driver.H"
+#include <FL/fl_draw.H>
+#include <cairo/cairo.h>
+#include <pango/pangocairo.h>
+
+// duplicated from Fl_PostScript.cxx
+struct callback_data {
+  const uchar *data;
+  int D, LD;
+};
+static const 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}
+};
+static const 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}
+};
+static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
+  struct callback_data *cb_data;
+  const uchar *curdata;
+
+  cb_data = (struct callback_data*)data;
+  int last = x+w;
+  curdata = cb_data->data + x*cb_data->D + y*cb_data->LD;
+  for (; x<last; x++) {
+    memcpy(buf, curdata, abs(cb_data->D));
+    buf += abs(cb_data->D);
+    curdata += cb_data->D;
+  }
+}
+
+
+Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver() : Fl_Graphics_Driver() {}
+
+Fl_Cairo_Graphics_Driver::~Fl_Cairo_Graphics_Driver() {}
+
+
+void Fl_Cairo_Graphics_Driver::rectf(int x, int y, int w, int h) {
+  cairo_rectangle(cairo_, x, y, w, h);
+  cairo_fill(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::rect(int x, int y, int w, int h) {
+  cairo_rectangle(cairo_, x, y, w, h);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
+  cairo_new_path(cairo_);
+  cairo_move_to(cairo_, x1, y1);
+  cairo_line_to(cairo_, x2, y2);
+  cairo_stroke(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) {
+  cairo_new_path(cairo_);
+  cairo_move_to(cairo_, x0, y0);
+  cairo_line_to(cairo_, x1, y1);
+  cairo_line_to(cairo_, x2, y2);
+  cairo_stroke(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1) {
+  cairo_move_to(cairo_, x, y);
+  cairo_line_to(cairo_, x1, y);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+  cairo_move_to(cairo_, x, y);
+  cairo_line_to(cairo_, x1, y);
+  cairo_line_to(cairo_, x1, y2);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+  cairo_move_to(cairo_, x, y);
+  cairo_line_to(cairo_, x1, y);
+  cairo_line_to(cairo_, x1, y2);
+  cairo_line_to(cairo_, x3, y2);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1) {
+  cairo_move_to(cairo_, x, y);
+  cairo_line_to(cairo_, x, y1);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+  cairo_move_to(cairo_, x, y);
+  cairo_line_to(cairo_, x, y1);
+  cairo_line_to(cairo_, x2, y1);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+  cairo_move_to(cairo_, x, y);
+  cairo_line_to(cairo_, x, y1);
+  cairo_line_to(cairo_, x2, y1);
+  cairo_line_to(cairo_, x2, y3);
+  cairo_stroke(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
+  cairo_save(cairo_);
+  cairo_new_path(cairo_);
+  cairo_move_to(cairo_, x0, y0);
+  cairo_line_to(cairo_, x1, y1);
+  cairo_line_to(cairo_, x2, y2);
+  cairo_close_path(cairo_);
+  cairo_stroke(cairo_);
+  cairo_restore(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  cairo_save(cairo_);
+  cairo_new_path(cairo_);
+  cairo_move_to(cairo_, x0, y0);
+  cairo_line_to(cairo_, x1, y1);
+  cairo_line_to(cairo_, x2, y2);
+  cairo_line_to(cairo_, x3, y3);
+  cairo_close_path(cairo_);
+  cairo_stroke(cairo_);
+  cairo_restore(cairo_);
+
+}
+
+void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
+  cairo_save(cairo_);
+  cairo_new_path(cairo_);
+  cairo_move_to(cairo_, x0, y0);
+  cairo_line_to(cairo_, x1, y1);
+  cairo_line_to(cairo_, x2, y2);
+  cairo_close_path(cairo_);
+  cairo_fill(cairo_);
+  cairo_restore(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  cairo_save(cairo_);
+  cairo_new_path(cairo_);
+  cairo_move_to(cairo_, x0, y0);
+  cairo_line_to(cairo_, x1, y1);
+  cairo_line_to(cairo_, x2, y2);
+  cairo_line_to(cairo_, x3, y3);
+  cairo_close_path(cairo_);
+  cairo_fill(cairo_);
+  cairo_restore(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::line_style(int style, int width, char* dashes) {
+  linewidth_=width;
+  linestyle_=style;
+  if(dashes){
+    if(dashes != linedash_)
+      strcpy(linedash_,dashes);
+
+  } else
+    linedash_[0]=0;
+  char width0 = 0;
+  if (!width){
+    width=1; //for screen drawing compatibility
+    width0=1;
+  }
+  cairo_set_line_width(cairo_, width);
+
+  if(!style && (!dashes || !(*dashes)) && width0) //system lines
+    style = FL_CAP_SQUARE;
+
+  int cap = (style &0xf00);
+  cairo_line_cap_t c_cap;
+  if (cap == FL_CAP_SQUARE) c_cap = CAIRO_LINE_CAP_SQUARE;
+  else if (cap == FL_CAP_FLAT) c_cap = CAIRO_LINE_CAP_BUTT;
+  else if (cap == FL_CAP_ROUND) c_cap = CAIRO_LINE_CAP_ROUND;
+  else c_cap = CAIRO_LINE_CAP_BUTT;
+  cairo_set_line_cap(cairo_, c_cap);
+
+  int join = (style & 0xf000);
+  cairo_line_join_t c_join;
+  if (join == FL_JOIN_MITER) c_join = CAIRO_LINE_JOIN_MITER;
+  else if (join == FL_JOIN_ROUND)c_join = CAIRO_LINE_JOIN_ROUND;
+  else if (join == FL_JOIN_BEVEL) c_join = CAIRO_LINE_JOIN_BEVEL;
+  else c_join = CAIRO_LINE_JOIN_MITER;
+  cairo_set_line_join(cairo_, c_join);
+
+  double *ddashes = NULL;
+  int l = 0;
+  if (dashes && *dashes){
+    ddashes = new double[strlen(dashes)];
+    while (dashes[l]) {ddashes[l] = dashes[l]; l++; }
+  } else if (style & 0xff) {
+    ddashes = new double[6];
+    if (style & 0x200){ // round and square caps, dash length need to be adjusted
+      const double *dt = dashes_cap[style & 0xff];
+      while (*dt >= 0){
+        ddashes[l++] = width * (*dt);
+        dt++;
+      }
+    } else {
+      const int *ds = dashes_flat[style & 0xff];
+      while (*ds >= 0){
+        ddashes[l++] = width * (*ds);
+        ds++;
+      }
+    }
+  }
+  cairo_set_dash(cairo_, ddashes, l, 0);
+  delete[] ddashes;
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) {
+  Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
+  cr_ = r; cg_ = g; cb_ = b;
+  double fr, fg, fb;
+  fr = r/255.0;
+  fg = g/255.0;
+  fb = b/255.0;
+  cairo_set_source_rgb(cairo_, fr, fg, fb);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::color(Fl_Color c) {
+  Fl::get_color(c, cr_, cg_, cb_);
+  Fl_Cairo_Graphics_Driver::color(cr_, cg_, cb_);
+}
+
+Fl_Color Fl_Cairo_Graphics_Driver::color() { return Fl_Graphics_Driver::color(); }
+
+void Fl_Cairo_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y)
+{
+  cairo_save(cairo_);
+  cairo_translate(cairo_, x, y);
+  cairo_rotate(cairo_, -rotation * M_PI / 180);
+  this->transformed_draw(str, n, 0, 0);
+  cairo_restore(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) {
+  if (!n) return;
+  pango_layout_set_font_description(pango_layout_, pango_font_description(Fl_Graphics_Driver::font()));
+  int pwidth, pheight;
+  cairo_save(cairo_);
+  pango_layout_set_text(pango_layout_, str, n);
+  pango_layout_get_size(pango_layout_, &pwidth, &pheight);
+  if (pwidth > 0) {
+    double s = width(str, n);
+    cairo_translate(cairo_, x, y - height() + descent());
+    s = (s/pwidth) * PANGO_SCALE;
+    cairo_scale(cairo_, s, s);
+    pango_cairo_show_layout(cairo_, pango_layout_);
+  }
+  cairo_restore(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
+  int w = (int)width(str, n);
+  transformed_draw(str, n, x - w, y);
+}
+
+void Fl_Cairo_Graphics_Driver::concat(){
+  cairo_matrix_t mat = {fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y};
+  cairo_transform(cairo_, &mat);
+}
+
+void Fl_Cairo_Graphics_Driver::reconcat(){
+  cairo_matrix_t mat = {fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y};
+  cairo_status_t stat = cairo_matrix_invert(&mat);
+  if (stat != CAIRO_STATUS_SUCCESS) {
+    fputs("error in cairo_matrix_invert\n", stderr);
+  }
+  cairo_transform(cairo_, &mat);
+}
+
+void Fl_Cairo_Graphics_Driver::begin_points() {
+  cairo_save(cairo_);
+  concat();
+  cairo_new_path(cairo_);
+  gap_=1;
+  shape_=POINTS;
+}
+
+void Fl_Cairo_Graphics_Driver::begin_line() {
+  cairo_save(cairo_);
+  concat();
+  cairo_new_path(cairo_);
+  gap_=1;
+  shape_=LINE;
+}
+
+void Fl_Cairo_Graphics_Driver::begin_loop() {
+  cairo_save(cairo_);
+  concat();
+  cairo_new_path(cairo_);
+  gap_=1;
+  shape_=LOOP;
+}
+
+void Fl_Cairo_Graphics_Driver::begin_polygon() {
+  cairo_save(cairo_);
+  concat();
+  cairo_new_path(cairo_);
+  gap_=1;
+  shape_=POLYGON;
+}
+
+void Fl_Cairo_Graphics_Driver::vertex(double x, double y) {
+  if(shape_==POINTS){
+    cairo_move_to(cairo_, x, y);
+    gap_=1;
+    return;
+  }
+  if(gap_){
+    cairo_move_to(cairo_, x, y);
+    gap_=0;
+  }else
+    cairo_line_to(cairo_, x, y);
+}
+
+void Fl_Cairo_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_)
+    cairo_move_to(cairo_, x, y);
+  else
+    cairo_line_to(cairo_, x, y);
+  gap_=0;
+  cairo_curve_to(cairo_, x1 , y1 , x2 , y2 , x3 , y3);
+}
+
+void Fl_Cairo_Graphics_Driver::circle(double x, double y, double r){
+  if (shape_==NONE){
+    cairo_save(cairo_);
+    concat();
+    cairo_arc(cairo_, x, y, r, 0, 2*M_PI);
+    reconcat();
+    cairo_restore(cairo_);
+  } else
+    cairo_arc(cairo_, x, y, r, 0, 2*M_PI);
+}
+
+void Fl_Cairo_Graphics_Driver::arc(double x, double y, double r, double start, double a){
+  if (shape_==NONE) return;
+  gap_ = 0;
+  if(start > a)
+    cairo_arc(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180);
+  else
+    cairo_arc_negative(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180);
+}
+
+void Fl_Cairo_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
+  if (w <= 1 || h <= 1) return;
+  cairo_save(cairo_);
+  begin_line();
+  cairo_translate(cairo_, x + w/2.0 -0.5 , y + h/2.0 - 0.5);
+  cairo_scale(cairo_, (w-1)/2.0 , (h-1)/2.0);
+  arc(0,0,1,a2,a1);
+  cairo_scale(cairo_, 2.0/(w-1) , 2.0/(h-1));
+  cairo_translate(cairo_, -x - w/2.0 +0.5 , -y - h/2.0 +0.5);
+  end_line();
+  cairo_restore(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {
+  cairo_save(cairo_);
+  begin_polygon();
+  cairo_translate(cairo_, x + w/2.0 -0.5 , y + h/2.0 - 0.5);
+  cairo_scale(cairo_, (w-1)/2.0 , (h-1)/2.0);
+  vertex(0,0);
+  arc(0.0,0.0, 1, a2, a1);
+  end_polygon();
+  cairo_restore(cairo_);
+}
+
+void Fl_Cairo_Graphics_Driver::end_points() {
+  end_line();
+}
+
+void Fl_Cairo_Graphics_Driver::end_line() {
+  gap_=1;
+  reconcat();
+  cairo_stroke(cairo_);
+  cairo_restore(cairo_);
+  shape_=NONE;
+}
+
+void Fl_Cairo_Graphics_Driver::end_loop(){
+  gap_=1;
+  reconcat();
+  cairo_close_path(cairo_);
+  cairo_stroke(cairo_);
+  cairo_restore(cairo_);
+  shape_=NONE;
+}
+
+void Fl_Cairo_Graphics_Driver::end_polygon() {
+  gap_=1;
+  reconcat();
+  cairo_close_path(cairo_);
+  cairo_fill(cairo_);
+  cairo_restore(cairo_);
+  shape_=NONE;
+}
+
+void Fl_Cairo_Graphics_Driver::transformed_vertex(double x, double y) {
+  reconcat();
+  if(gap_){
+    cairo_move_to(cairo_, x, y);
+    gap_=0;
+  }else
+    cairo_line_to(cairo_, x, y);
+  concat();
+}
+
+void Fl_Cairo_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;
+  cairo_save(cairo_);
+  cairo_rectangle(cairo_, clip_->x-0.5 , clip_->y-0.5 , clip_->w  , clip_->h);
+  cairo_clip(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::push_no_clip() {
+  Clip * c = new Clip();
+  c->prev=clip_;
+  clip_=c;
+  clip_->x = clip_->y = clip_->w = clip_->h = -1;
+  cairo_save(cairo_);
+  cairo_reset_clip(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::pop_clip() {
+  if(!clip_)return;
+  Clip * c=clip_;
+  clip_=clip_->prev;
+  delete c;
+  cairo_restore(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::ps_origin(int x, int y) {
+  cairo_restore(cairo_);
+  cairo_restore(cairo_);
+  cairo_save(cairo_);
+  cairo_scale(cairo_, scale_x, scale_y);
+  cairo_translate(cairo_, x, y);
+  cairo_rotate(cairo_, angle * M_PI / 180);
+  cairo_save(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::ps_translate(int x, int y)
+{
+  cairo_save(cairo_);
+  cairo_translate(cairo_, x, y);
+  cairo_save(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::ps_untranslate(void)
+{
+  cairo_restore(cairo_);
+  cairo_restore(cairo_);
+  check_status();
+}
+
+void Fl_Cairo_Graphics_Driver::check_status(void) {
+#ifdef DEBUG
+  if (cairo_status(cairo_) !=  CAIRO_STATUS_SUCCESS) {
+    fprintf(stderr,"we have a problem");
+  }
+#endif
+}
+
+void Fl_Cairo_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
+{
+  uchar *array = new uchar[iw * D * ih];
+  for (int l = 0; l < ih; l++) {
+    call(data, 0, l, iw, array + l*D*iw);
+    if (D%2 == 0) for (int i = 0; i < iw; i++) {
+      *(array + l*D*iw + i*D + D-1) = 0xff;
+    }
+  }
+  Fl_RGB_Image *rgb = new Fl_RGB_Image(array, iw, ih, D);
+  rgb->alloc_array  = 1;
+  draw_rgb(rgb, ix, iy, iw, ih, 0, 0);
+  delete rgb;
+}
+
+void Fl_Cairo_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD)
+{
+  struct callback_data cb_data;
+  if (!LD) LD = iw*abs(D);
+  if (D<0) data += iw*abs(D);
+  cb_data.data = data;
+  cb_data.D = D;
+  cb_data.LD = LD;
+  draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D));
+}
+
+void Fl_Cairo_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
+{
+  draw_image(call, data, ix, iy, iw, ih, D);
+}
+
+static void destroy_BGRA(void *data) {
+  delete[] (uchar*)data;
+}
+
+void Fl_Cairo_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
+  Fl_RGB_Image *rgb =  new Fl_RGB_Image(pxm);
+  draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
+  delete rgb;
+}
+
+void Fl_Cairo_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
+  draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
+}
+
+void Fl_Cairo_Graphics_Driver::draw_bitmap(Fl_Bitmap *bitmap,int XP, int YP, int WP, int HP, int cx, int cy) {
+  draw_rgb_bitmap_(bitmap, XP, YP, WP, HP, cx, cy);
+}
+
+void Fl_Cairo_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy)
+{
+  cairo_surface_t *surf;
+  cairo_format_t format = (img->d() >= 1 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A1);
+  int stride = cairo_format_stride_for_width(format, img->data_w());
+  uchar *BGRA = new uchar[stride * img->data_h()];
+  memset(BGRA, 0, stride * img->data_h());
+  if (img->d() >= 1) { // process Fl_RGB_Image of all depths
+    Fl_RGB_Image *rgb = (Fl_RGB_Image*)img;
+    int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
+    uchar A = 0xff, R,G,B, *q;
+    const uchar *r;
+    float f = 1;
+    if (rgb->d() >= 3) { // color images
+       for (int j = 0; j < rgb->data_h(); j++) {
+        r = rgb->array + j * lrgb;
+        q = BGRA + j * stride;
+        for (int i = 0; i < rgb->data_w(); i++) {
+          R = *r;
+          G = *(r+1);
+          B = *(r+2);
+          if (rgb->d() == 4) {
+            A = *(r+3);
+            f = float(A)/0xff;
+          }
+          *q =  B * f;
+          *(q+1) =  G * f;
+          *(q+2) =  R * f;
+          *(q+3) =  A;
+          r += rgb->d(); q += 4;
+        }
+      }
+    } else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
+      for (int j = 0; j < rgb->data_h(); j++) {
+        r = rgb->array + j * lrgb;
+        q = BGRA + j * stride;
+        for (int i = 0; i < rgb->data_w(); i++) {
+          G = *r;
+          if (rgb->d() == 2) {
+            A = *(r+1);
+            f = float(A)/0xff;
+          }
+          *(q) =  G * f;
+          *(q+1) =  G * f;
+          *(q+2) =  G * f;
+          *(q+3) =  A;
+          r += rgb->d(); q += 4;
+        }
+      }
+    }
+  } else {
+    Fl_Bitmap *bm = (Fl_Bitmap*)img;
+    uchar  *r, p;
+    unsigned *q;
+    for (int j = 0; j < bm->data_h(); j++) {
+      r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8);
+      q = (unsigned*)(BGRA + j * stride);
+      unsigned k = 0, mask32 = 1;
+      p = *r;
+      for (int i = 0; i < bm->data_w(); i++) {
+        if (p&1) (*q) |= mask32;
+        k++;
+        if (k % 8 != 0) p >>= 1; else p = *(++r);
+        if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
+      }
+    }
+  }
+  surf = cairo_image_surface_create_for_data(BGRA, format, img->data_w(), img->data_h(), stride);
+  if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
+    static cairo_user_data_key_t key = {};
+    (void)cairo_surface_set_user_data(surf, &key, BGRA, destroy_BGRA);
+    cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
+    cairo_save(cairo_);
+    cairo_rectangle(cairo_, XP-0.5, YP-0.5, WP+1, HP+1);
+    cairo_clip(cairo_);
+    if (img->d() >= 1) cairo_set_source(cairo_, pat);
+    cairo_matrix_t matrix;
+    cairo_matrix_init_scale(&matrix, double(img->data_w())/(img->w()+1), double(img->data_h())/(img->h()+1));
+    cairo_matrix_translate(&matrix, -XP+0.5+cx, -YP+0.5+cy);
+    cairo_pattern_set_matrix(pat, &matrix);
+    cairo_mask(cairo_, pat);
+    cairo_pattern_destroy(pat);
+    cairo_surface_destroy(surf);
+    cairo_restore(cairo_);
+    check_status();
+  }
+}
+
+#endif // USE_PANGO
diff --git src/drivers/PostScript/Fl_PostScript.cxx src/drivers/PostScript/Fl_PostScript.cxx
index 53811d6..c041923 100644
--- src/drivers/PostScript/Fl_PostScript.cxx
+++ src/drivers/PostScript/Fl_PostScript.cxx
@@ -100,6 +100,7 @@ Fl_PostScript_File_Device::~Fl_PostScript_File_Device() {
  \{
  */
 
+#if ! USE_PANGO
 static const int dashes_flat[5][7]={
 {-1,0,0,0,0,0,0},
 {3,1,-1,0,0,0,0},
@@ -116,6 +117,7 @@ static const double dashes_cap[5][7]={
 {2,2,0.01,1.99,-1,0,0},
 {2,2,0.01,1.99,0.01,1.99,-1}
 };
+#endif
 
 /**
  \brief The constructor.
@@ -1500,448 +1502,8 @@ int Fl_PostScript_Graphics_Driver::start_eps(int width, int height) {
   return 0;
 }
 
-void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) {
-  cairo_rectangle(cairo_, x, y, w, h);
-  cairo_fill(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) {
-  cairo_rectangle(cairo_, x, y, w, h);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
-  cairo_new_path(cairo_);
-  cairo_move_to(cairo_, x1, y1);
-  cairo_line_to(cairo_, x2, y2);
-  cairo_stroke(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) {
-  cairo_new_path(cairo_);
-  cairo_move_to(cairo_, x0, y0);
-  cairo_line_to(cairo_, x1, y1);
-  cairo_line_to(cairo_, x2, y2);
-  cairo_stroke(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1) {
-  cairo_move_to(cairo_, x, y);
-  cairo_line_to(cairo_, x1, y);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
-  cairo_move_to(cairo_, x, y);
-  cairo_line_to(cairo_, x1, y);
-  cairo_line_to(cairo_, x1, y2);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
-  cairo_move_to(cairo_, x, y);
-  cairo_line_to(cairo_, x1, y);
-  cairo_line_to(cairo_, x1, y2);
-  cairo_line_to(cairo_, x3, y2);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1) {
-  cairo_move_to(cairo_, x, y);
-  cairo_line_to(cairo_, x, y1);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
-  cairo_move_to(cairo_, x, y);
-  cairo_line_to(cairo_, x, y1);
-  cairo_line_to(cairo_, x2, y1);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
-  cairo_move_to(cairo_, x, y);
-  cairo_line_to(cairo_, x, y1);
-  cairo_line_to(cairo_, x2, y1);
-  cairo_line_to(cairo_, x2, y3);
-  cairo_stroke(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
-  cairo_save(cairo_);
-  cairo_new_path(cairo_);
-  cairo_move_to(cairo_, x0, y0);
-  cairo_line_to(cairo_, x1, y1);
-  cairo_line_to(cairo_, x2, y2);
-  cairo_close_path(cairo_);
-  cairo_stroke(cairo_);
-  cairo_restore(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
-  cairo_save(cairo_);
-  cairo_new_path(cairo_);
-  cairo_move_to(cairo_, x0, y0);
-  cairo_line_to(cairo_, x1, y1);
-  cairo_line_to(cairo_, x2, y2);
-  cairo_line_to(cairo_, x3, y3);
-  cairo_close_path(cairo_);
-  cairo_stroke(cairo_);
-  cairo_restore(cairo_);
-
-}
-
-void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
-  cairo_save(cairo_);
-  cairo_new_path(cairo_);
-  cairo_move_to(cairo_, x0, y0);
-  cairo_line_to(cairo_, x1, y1);
-  cairo_line_to(cairo_, x2, y2);
-  cairo_close_path(cairo_);
-  cairo_fill(cairo_);
-  cairo_restore(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
-  cairo_save(cairo_);
-  cairo_new_path(cairo_);
-  cairo_move_to(cairo_, x0, y0);
-  cairo_line_to(cairo_, x1, y1);
-  cairo_line_to(cairo_, x2, y2);
-  cairo_line_to(cairo_, x3, y3);
-  cairo_close_path(cairo_);
-  cairo_fill(cairo_);
-  cairo_restore(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashes) {
-  linewidth_=width;
-  linestyle_=style;
-  if(dashes){
-    if(dashes != linedash_)
-      strcpy(linedash_,dashes);
-
-  } else
-    linedash_[0]=0;
-  char width0 = 0;
-  if (!width){
-    width=1; //for screen drawing compatibility
-    width0=1;
-  }
-  cairo_set_line_width(cairo_, width);
-
-  if(!style && (!dashes || !(*dashes)) && width0) //system lines
-    style = FL_CAP_SQUARE;
-
-  int cap = (style &0xf00);
-  cairo_line_cap_t c_cap;
-  if (cap == FL_CAP_SQUARE) c_cap = CAIRO_LINE_CAP_SQUARE;
-  else if (cap == FL_CAP_FLAT) c_cap = CAIRO_LINE_CAP_BUTT;
-  else if (cap == FL_CAP_ROUND) c_cap = CAIRO_LINE_CAP_ROUND;
-  else c_cap = CAIRO_LINE_CAP_BUTT;
-  cairo_set_line_cap(cairo_, c_cap);
-
-  int join = (style & 0xf000);
-  cairo_line_join_t c_join;
-  if (join == FL_JOIN_MITER) c_join = CAIRO_LINE_JOIN_MITER;
-  else if (join == FL_JOIN_ROUND)c_join = CAIRO_LINE_JOIN_ROUND;
-  else if (join == FL_JOIN_BEVEL) c_join = CAIRO_LINE_JOIN_BEVEL;
-  else c_join = CAIRO_LINE_JOIN_MITER;
-  cairo_set_line_join(cairo_, c_join);
-
-  double *ddashes = NULL;
-  int l = 0;
-  if (dashes && *dashes){
-    ddashes = new double[strlen(dashes)];
-    while (dashes[l]) {ddashes[l] = dashes[l]; l++; }
-  } else if (style & 0xff) {
-    ddashes = new double[6];
-    if (style & 0x200){ // round and square caps, dash length need to be adjusted
-      const double *dt = dashes_cap[style & 0xff];
-      while (*dt >= 0){
-        ddashes[l++] = width * (*dt);
-        dt++;
-      }
-    } else {
-      const int *ds = dashes_flat[style & 0xff];
-      while (*ds >= 0){
-        ddashes[l++] = width * (*ds);
-        ds++;
-      }
-    }
-  }
-  cairo_set_dash(cairo_, ddashes, l, 0);
-  delete[] ddashes;
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) {
-  Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
-  cr_ = r; cg_ = g; cb_ = b;
-  double fr, fg, fb;
-  fr = r/255.0;
-  fg = g/255.0;
-  fb = b/255.0;
-  cairo_set_source_rgb(cairo_, fr, fg, fb);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y)
-{
-  cairo_save(cairo_);
-  cairo_translate(cairo_, x, y);
-  cairo_rotate(cairo_, -rotation * M_PI / 180);
-  this->transformed_draw(str, n, 0, 0);
-  cairo_restore(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) {
-  if (!n) return;
-  pango_layout_set_font_description(pango_layout_, Fl_Xlib_Graphics_Driver::pango_font_description(Fl_Graphics_Driver::font()));
-  int pwidth, pheight;
-  cairo_save(cairo_);
-  pango_layout_set_text(pango_layout_, str, n);
-  pango_layout_get_size(pango_layout_, &pwidth, &pheight);
-  if (pwidth > 0) {
-    double s = width(str, n);
-    cairo_translate(cairo_, x, y - height() + descent());
-    s = (s/pwidth) * PANGO_SCALE;
-    cairo_scale(cairo_, s, s);
-    pango_cairo_show_layout(cairo_, pango_layout_);
-  }
-  cairo_restore(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
-  int w = (int)width(str, n);
-  transformed_draw(str, n, x - w, y);
-}
-
-void Fl_PostScript_Graphics_Driver::concat(){
-  cairo_matrix_t mat = {fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y};
-  cairo_transform(cairo_, &mat);
-}
-
-void Fl_PostScript_Graphics_Driver::reconcat(){
-  cairo_matrix_t mat = {fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y};
-  cairo_status_t stat = cairo_matrix_invert(&mat);
-  if (stat != CAIRO_STATUS_SUCCESS) {
-    fputs("error in cairo_matrix_invert\n", stderr);
-  }
-  cairo_transform(cairo_, &mat);
-}
-
-void Fl_PostScript_Graphics_Driver::begin_points() {
-  cairo_save(cairo_);
-  concat();
-  cairo_new_path(cairo_);
-  gap_=1;
-  shape_=POINTS;
-}
-
-void Fl_PostScript_Graphics_Driver::begin_line() {
-  cairo_save(cairo_);
-  concat();
-  cairo_new_path(cairo_);
-  gap_=1;
-  shape_=LINE;
-}
-
-void Fl_PostScript_Graphics_Driver::begin_loop() {
-  cairo_save(cairo_);
-  concat();
-  cairo_new_path(cairo_);
-  gap_=1;
-  shape_=LOOP;
-}
-
-void Fl_PostScript_Graphics_Driver::begin_polygon() {
-  cairo_save(cairo_);
-  concat();
-  cairo_new_path(cairo_);
-  gap_=1;
-  shape_=POLYGON;
-}
-
-void Fl_PostScript_Graphics_Driver::vertex(double x, double y) {
-  if(shape_==POINTS){
-    cairo_move_to(cairo_, x, y);
-    gap_=1;
-    return;
-  }
-  if(gap_){
-    cairo_move_to(cairo_, x, y);
-    gap_=0;
-  }else
-    cairo_line_to(cairo_, 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_)
-    cairo_move_to(cairo_, x, y);
-  else
-    cairo_line_to(cairo_, x, y);
-  gap_=0;
-  cairo_curve_to(cairo_, x1 , y1 , x2 , y2 , x3 , y3);
-}
-
-void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){
-  if (shape_==NONE){
-    cairo_save(cairo_);
-    concat();
-    cairo_arc(cairo_, x, y, r, 0, 2*M_PI);
-    reconcat();
-    cairo_restore(cairo_);
-  } else
-    cairo_arc(cairo_, x, y, r, 0, 2*M_PI);
-}
-
-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)
-    cairo_arc(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180);
-  else
-    cairo_arc_negative(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180);
-}
-
-void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
-  if (w <= 1 || h <= 1) return;
-  cairo_save(cairo_);
-  begin_line();
-  cairo_translate(cairo_, x + w/2.0 -0.5 , y + h/2.0 - 0.5);
-  cairo_scale(cairo_, (w-1)/2.0 , (h-1)/2.0);
-  arc(0,0,1,a2,a1);
-  cairo_scale(cairo_, 2.0/(w-1) , 2.0/(h-1));
-  cairo_translate(cairo_, -x - w/2.0 +0.5 , -y - h/2.0 +0.5);
-  end_line();
-  cairo_restore(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {
-  cairo_save(cairo_);
-  begin_polygon();
-  cairo_translate(cairo_, x + w/2.0 -0.5 , y + h/2.0 - 0.5);
-  cairo_scale(cairo_, (w-1)/2.0 , (h-1)/2.0);
-  vertex(0,0);
-  arc(0.0,0.0, 1, a2, a1);
-  end_polygon();
-  cairo_restore(cairo_);
-}
-
-void Fl_PostScript_Graphics_Driver::end_points() {
-  end_line();
-}
-
-void Fl_PostScript_Graphics_Driver::end_line() {
-  gap_=1;
-  reconcat();
-  cairo_stroke(cairo_);
-  cairo_restore(cairo_);
-  shape_=NONE;
-}
-
-void Fl_PostScript_Graphics_Driver::end_loop(){
-  gap_=1;
-  reconcat();
-  cairo_close_path(cairo_);
-  cairo_stroke(cairo_);
-  cairo_restore(cairo_);
-  shape_=NONE;
-}
-
-void Fl_PostScript_Graphics_Driver::end_polygon() {
-  gap_=1;
-  reconcat();
-  cairo_close_path(cairo_);
-  cairo_fill(cairo_);
-  cairo_restore(cairo_);
-  shape_=NONE;
-}
-
-void Fl_PostScript_Graphics_Driver::transformed_vertex(double x, double y) {
-  reconcat();
-  if(gap_){
-    cairo_move_to(cairo_, x, y);
-    gap_=0;
-  }else
-    cairo_line_to(cairo_, x, y);
-  concat();
-}
-
-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;
-  cairo_save(cairo_);
-  cairo_rectangle(cairo_, clip_->x-0.5 , clip_->y-0.5 , clip_->w  , clip_->h);
-  cairo_clip(cairo_);
-  check_status();
-}
-
-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;
-  cairo_save(cairo_);
-  cairo_reset_clip(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::pop_clip() {
-  if(!clip_)return;
-  Clip * c=clip_;
-  clip_=clip_->prev;
-  delete c;
-  cairo_restore(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::ps_origin(int x, int y) {
-  cairo_restore(cairo_);
-  cairo_restore(cairo_);
-  cairo_save(cairo_);
-  cairo_scale(cairo_, scale_x, scale_y);
-  cairo_translate(cairo_, x, y);
-  cairo_rotate(cairo_, angle * M_PI / 180);
-  cairo_save(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::ps_translate(int x, int y)
-{
-  cairo_save(cairo_);
-  cairo_translate(cairo_, x, y);
-  cairo_save(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::ps_untranslate(void)
-{
-  cairo_restore(cairo_);
-  cairo_restore(cairo_);
-  check_status();
-}
-
-void Fl_PostScript_Graphics_Driver::check_status(void) {
-#ifdef DEBUG
-  if (cairo_status(cairo_) !=  CAIRO_STATUS_SUCCESS) {
-    fprintf(stderr,"we have a problem");
-  }
-#endif
+PangoFontDescription* Fl_PostScript_Graphics_Driver::pango_font_description(Fl_Font fnum) {
+  return Fl_Xlib_Graphics_Driver::pango_font_description(fnum);
 }
 
 #endif // USE_PANGO
diff --git src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H
index 80019fd..5c15e0e 100644
--- src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H
+++ src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H
@@ -28,11 +28,6 @@
 #define USE_PANGO 0
 #endif
 
-#if USE_PANGO
-typedef struct _cairo cairo_t;
-typedef struct _PangoLayout  PangoLayout;
-#endif
-
 /**
  \cond DriverDev
  \addtogroup DriverDeveloper
@@ -42,14 +37,51 @@ typedef struct _PangoLayout  PangoLayout;
 /**
  PostScript graphical backend.
  */
+#if USE_PANGO
+
+#include "../Cairo/Fl_Cairo_Graphics_Driver.H"
+
+class FL_EXPORT Fl_PostScript_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
+public:
+  FILE *output;
+  Fl_PostScript_Close_Command close_cmd_;
+  enum Fl_Paged_Device::Page_Format page_format_;
+  char *ps_filename_;
+  int nPages;
+  
+  Fl_PostScript_Graphics_Driver();
+  ~Fl_PostScript_Graphics_Driver();
+  void close_command(Fl_PostScript_Close_Command cmd){close_cmd_=cmd;};
+  FILE * file() {return output;};
+  void page(double pw, double ph, int media = 0);
+  void page(int format);
+  int start_postscript (int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout);
+  int start_eps(int width, int height);
+  void draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD);
+  void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3) {
+    Fl_Cairo_Graphics_Driver::draw_image(call, data, x,y,w,h,delta);
+  }
+  void font(int f, int s);
+  Fl_Font font();
+  double width(const char *s, int n);
+  double width(unsigned u);
+  int height();
+  int descent();
+  void text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h);
+  void color(Fl_Color c);
+  void color(uchar r, uchar g, uchar b) {Fl_Cairo_Graphics_Driver::color(r,g,b);}
+  Fl_Color color();
+  void point(int x, int y);
+  int not_clipped(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);
+  virtual PangoFontDescription* pango_font_description(Fl_Font fnum);
+  virtual int has_feature(driver_feature feature_mask) { return feature_mask & PRINTER; }
+};
+
+#else // USE_PANGO
 
 class FL_EXPORT Fl_PostScript_Graphics_Driver : public Fl_Graphics_Driver {
 private:
-#if USE_PANGO
-  cairo_t *cairo_;
-  PangoLayout *pango_layout_;
-  void draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy);
-#else
   void transformed_draw_extra(const char* str, int n, double x, double y, int w, bool rtl);
   void *prepare_rle85();
   void write_rle85(uchar b, void *data);
@@ -58,14 +90,10 @@ private:
   void write85(void *data, const uchar *p, int len);
   void close85(void *data);
   int scale_for_image_(Fl_Image *img, int XP, int YP, int WP, int HP,int cx, int cy);
-#endif
 protected:
-#if ! USE_PANGO
   uchar **mask_bitmap() {return &mask;}
-#endif
 public:
   Fl_PostScript_Graphics_Driver();
-#ifndef FL_DOXYGEN
   enum SHAPE {NONE=0, LINE, LOOP, POLYGON, POINTS};
 
   class Clip {
@@ -78,11 +106,6 @@ public:
   int lang_level_;
   int gap_;
   int pages_;
-#if USE_PANGO
-  cairo_t *cr() { return cairo_; }
-  PangoLayout *pango_layout() {return pango_layout_;};
-  void check_status(void);
-#else
   int interpolate_; //interpolation of images
   uchar * mask;
   int mx; // width of mask;
@@ -98,7 +121,6 @@ public:
    \return value returned by vfprintf() call
    */
   int clocale_printf(const char *format, ...);
-#endif // USE_PANGO
 
   enum SHAPE shape_;
   int linewidth_;// need for clipping, lang level 1-2
@@ -141,7 +163,6 @@ public:
 
   void page(double pw, double ph, int media = 0);
   void page(int format);
-#endif // FL_DOXYGEN
 
   // implementation of drawing methods
   void color(Fl_Color c);
@@ -224,6 +245,7 @@ public:
   void ps_untranslate();
 };
 
+#endif // USE_PANGO
 /**
 \}
 \endcond
diff --git src/drivers/PostScript/Fl_PostScript_image.cxx src/drivers/PostScript/Fl_PostScript_image.cxx
index 102c1d4..ae53aaa 100644
--- src/drivers/PostScript/Fl_PostScript_image.cxx
+++ src/drivers/PostScript/Fl_PostScript_image.cxx
@@ -635,145 +635,6 @@ int Fl_PostScript_Graphics_Driver::scale_for_image_(Fl_Image *img, int XP, int Y
   return 0;
 }
 
-#else // USE_PANGO
-
-void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
-{
-  uchar *array = new uchar[iw * D * ih];
-  for (int l = 0; l < ih; l++) {
-    call(data, 0, l, iw, array + l*D*iw);
-    if (D%2 == 0) for (int i = 0; i < iw; i++) {
-      *(array + l*D*iw + i*D + D-1) = 0xff;
-    }
-  }
-  Fl_RGB_Image *rgb = new Fl_RGB_Image(array, iw, ih, D);
-  rgb->alloc_array  = 1;
-  draw_rgb(rgb, ix, iy, iw, ih, 0, 0);
-  delete rgb;
-}
-
-void Fl_PostScript_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD)
-{
-  struct callback_data cb_data;
-  if (!LD) LD = iw*abs(D);
-  if (D<0) data += iw*abs(D);
-  cb_data.data = data;
-  cb_data.D = D;
-  cb_data.LD = LD;
-  draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D));
-}
-
-void Fl_PostScript_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
-{
-  draw_image(call, data, ix, iy, iw, ih, D);
-}
-
-static void destroy_BGRA(void *data) {
-  delete[] (uchar*)data;
-}
-
-void Fl_PostScript_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
-  Fl_RGB_Image *rgb =  new Fl_RGB_Image(pxm);
-  draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
-  delete rgb;
-}
-
-void Fl_PostScript_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
-  draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
-}
-
-void Fl_PostScript_Graphics_Driver::draw_bitmap(Fl_Bitmap *bitmap,int XP, int YP, int WP, int HP, int cx, int cy) {
-  draw_rgb_bitmap_(bitmap, XP, YP, WP, HP, cx, cy);
-}
-
-void Fl_PostScript_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy)
-{
-  cairo_surface_t *surf;
-  cairo_format_t format = (img->d() >= 1 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A1);
-  int stride = cairo_format_stride_for_width(format, img->data_w());
-  uchar *BGRA = new uchar[stride * img->data_h()];
-  memset(BGRA, 0, stride * img->data_h());
-  if (img->d() >= 1) { // process Fl_RGB_Image of all depths
-    Fl_RGB_Image *rgb = (Fl_RGB_Image*)img;
-    int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
-    uchar A = 0xff, R,G,B, *q;
-    const uchar *r;
-    float f = 1;
-    if (rgb->d() >= 3) { // color images
-       for (int j = 0; j < rgb->data_h(); j++) {
-        r = rgb->array + j * lrgb;
-        q = BGRA + j * stride;
-        for (int i = 0; i < rgb->data_w(); i++) {
-          R = *r;
-          G = *(r+1);
-          B = *(r+2);
-          if (rgb->d() == 4) {
-            A = *(r+3);
-            f = float(A)/0xff;
-          }
-          *q =  B * f;
-          *(q+1) =  G * f;
-          *(q+2) =  R * f;
-          *(q+3) =  A;
-          r += rgb->d(); q += 4;
-        }
-      }
-    } else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
-      for (int j = 0; j < rgb->data_h(); j++) {
-        r = rgb->array + j * lrgb;
-        q = BGRA + j * stride;
-        for (int i = 0; i < rgb->data_w(); i++) {
-          G = *r;
-          if (rgb->d() == 2) {
-            A = *(r+1);
-            f = float(A)/0xff;
-          }
-          *(q) =  G * f;
-          *(q+1) =  G * f;
-          *(q+2) =  G * f;
-          *(q+3) =  A;
-          r += rgb->d(); q += 4;
-        }
-      }
-    }
-  } else {
-    Fl_Bitmap *bm = (Fl_Bitmap*)img;
-    uchar  *r, p;
-    unsigned *q;
-    for (int j = 0; j < bm->data_h(); j++) {
-      r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8);
-      q = (unsigned*)(BGRA + j * stride);
-      unsigned k = 0, mask32 = 1;
-      p = *r;
-      for (int i = 0; i < bm->data_w(); i++) {
-        if (p&1) (*q) |= mask32;
-        k++;
-        if (k % 8 != 0) p >>= 1; else p = *(++r);
-        if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
-      }
-    }
-  }
-  surf = cairo_image_surface_create_for_data(BGRA, format, img->data_w(), img->data_h(), stride);
-  if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
-    static cairo_user_data_key_t key = {};
-    (void)cairo_surface_set_user_data(surf, &key, BGRA, destroy_BGRA);
-    cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
-    cairo_save(cairo_);
-    cairo_rectangle(cairo_, XP-0.5, YP-0.5, WP+1, HP+1);
-    cairo_clip(cairo_);
-    if (img->d() >= 1) cairo_set_source(cairo_, pat);
-    cairo_matrix_t matrix;
-    cairo_matrix_init_scale(&matrix, double(img->data_w())/(img->w()+1), double(img->data_h())/(img->h()+1));
-    cairo_matrix_translate(&matrix, -XP+0.5+cx, -YP+0.5+cy);
-    cairo_pattern_set_matrix(pat, &matrix);
-    cairo_mask(cairo_, pat);
-    cairo_pattern_destroy(pat);
-    cairo_surface_destroy(surf);
-    cairo_restore(cairo_);
-    check_status();
-  }
-}
-
 #endif // USE_PANGO
 
 #endif // !defined(FL_DOXYGEN) && !defined(FL_NO_PRINT_SUPPORT)
Direct Link to Message ]
 
bottom left image   bottom right image
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2021 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.