Include a stripped-down version of FLTK in tree and add a USE_INCLUDED_FLTK option to build against it.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4603 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/fltk/src/fl_draw_image.cxx b/common/fltk/src/fl_draw_image.cxx
new file mode 100644
index 0000000..384a4c6
--- /dev/null
+++ b/common/fltk/src/fl_draw_image.cxx
@@ -0,0 +1,578 @@
+//
+// "$Id: fl_draw_image.cxx 8731 2011-05-23 21:05:22Z AlbrechtS $"
+//
+// Image drawing routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-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
+//
+
+// I hope a simple and portable method of drawing color and monochrome
+// images.  To keep this simple, only a single storage type is
+// supported: 8 bit unsigned data, byte order RGB, and pixels are
+// stored packed into rows with the origin at the top-left.  It is
+// possible to alter the size of pixels with the "delta" argument, to
+// add alpha or other information per pixel.  It is also possible to
+// change the origin and direction of the image data by messing with
+// the "delta" and "linedelta", making them negative, though this may
+// defeat some of the shortcuts in translating the image for X.
+
+#ifdef WIN32
+#  include "fl_draw_image_win32.cxx"
+#elif defined(__APPLE__)
+#  include "fl_draw_image_mac.cxx"
+#else
+
+// A list of assumptions made about the X display:
+
+// bits_per_pixel must be one of 8, 16, 24, 32.
+
+// scanline_pad must be a power of 2 and greater or equal to 8.
+
+// PsuedoColor visuals must have 8 bits_per_pixel (although the depth
+// may be less than 8).  This is the only limitation that affects any
+// modern X displays, you can't use 12 or 16 bit colormaps.
+
+// The mask bits in TrueColor visuals for each color are
+// contiguous and have at least one bit of each color.  This
+// is not checked for.
+
+// For 24 and 32 bit visuals there must be at least 8 bits of each color.
+
+////////////////////////////////////////////////////////////////
+
+#  include <FL/Fl.H>
+#  include <FL/fl_draw.H>
+#  include <FL/x.H>
+#  include "Fl_XColor.H"
+#  include "flstring.h"
+
+static XImage xi;	// template used to pass info to X
+static int bytes_per_pixel;
+static int scanline_add;
+static int scanline_mask;
+
+static void (*converter)(const uchar *from, uchar *to, int w, int delta);
+static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta);
+
+static int dir;		// direction-alternator
+static int ri,gi,bi;	// saved error-diffusion value
+
+#  if USE_COLORMAP
+////////////////////////////////////////////////////////////////
+// 8-bit converter with error diffusion
+
+static void color8_converter(const uchar *from, uchar *to, int w, int delta) {
+  int r=ri, g=gi, b=bi;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    to = to+(w-1);
+    d = -delta;
+    td = -1;
+  } else {
+    dir = 1;
+    d = delta;
+    td = 1;
+  }
+  for (; w--; from += d, to += td) {
+    r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+    g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
+    b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
+    Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+    Fl_XColor& xmap = fl_xmap[0][i];
+    if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);}
+    r -= xmap.r;
+    g -= xmap.g;
+    b -= xmap.b;
+    *to = uchar(xmap.pixel);
+  }
+  ri = r; gi = g; bi = b;
+}
+
+static void mono8_converter(const uchar *from, uchar *to, int w, int delta) {
+  int r=ri, g=gi, b=bi;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    to = to+(w-1);
+    d = -delta;
+    td = -1;
+  } else {
+    dir = 1;
+    d = delta;
+    td = 1;
+  }
+  for (; w--; from += d, to += td) {
+    r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+    g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255;
+    b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255;
+    Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+    Fl_XColor& xmap = fl_xmap[0][i];
+    if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);}
+    r -= xmap.r;
+    g -= xmap.g;
+    b -= xmap.b;
+    *to = uchar(xmap.pixel);
+  }
+  ri = r; gi = g; bi = b;
+}
+
+#  endif
+
+////////////////////////////////////////////////////////////////
+// 16 bit TrueColor converters with error diffusion
+// Cray computers have no 16-bit type, so we use character pointers
+// (which may be slow)
+
+#  ifdef U16
+#    define OUTTYPE U16
+#    define OUTSIZE 1
+#    define OUTASSIGN(v) *t = v
+#  else
+#    define OUTTYPE uchar
+#    define OUTSIZE 2
+#    define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt)
+#  endif
+
+static void color16_converter(const uchar *from, uchar *to, int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  int r=ri, g=gi, b=bi;
+  for (; w--; from += d, t += td) {
+    r = (r&~fl_redmask)  +from[0]; if (r>255) r = 255;
+    g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255;
+    b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255;
+    OUTASSIGN((
+      ((r&fl_redmask)<<fl_redshift)+
+      ((g&fl_greenmask)<<fl_greenshift)+
+      ((b&fl_bluemask)<<fl_blueshift)
+      ) >> fl_extrashift);
+  }
+  ri = r; gi = g; bi = b;
+}
+
+static void mono16_converter(const uchar *from,uchar *to,int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  uchar mask = fl_redmask & fl_greenmask & fl_bluemask;
+  int r=ri;
+  for (; w--; from += d, t += td) {
+    r = (r&~mask) + *from; if (r > 255) r = 255;
+    uchar m = r&mask;
+    OUTASSIGN((
+      (m<<fl_redshift)+
+      (m<<fl_greenshift)+
+      (m<<fl_blueshift)
+      ) >> fl_extrashift);
+  }
+  ri = r;
+}
+
+// special-case the 5r6g5b layout used by XFree86:
+
+static void c565_converter(const uchar *from, uchar *to, int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  int r=ri, g=gi, b=bi;
+  for (; w--; from += d, t += td) {
+    r = (r&7)+from[0]; if (r>255) r = 255;
+    g = (g&3)+from[1]; if (g>255) g = 255;
+    b = (b&7)+from[2]; if (b>255) b = 255;
+    OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3));
+  }
+  ri = r; gi = g; bi = b;
+}
+
+static void m565_converter(const uchar *from,uchar *to,int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  int r=ri;
+  for (; w--; from += d, t += td) {
+    r = (r&7) + *from; if (r > 255) r = 255;
+    OUTASSIGN((r>>3) * 0x841);
+  }
+  ri = r;
+}
+
+////////////////////////////////////////////////////////////////
+// 24bit TrueColor converters:
+
+static void rgb_converter(const uchar *from, uchar *to, int w, int delta) {
+  int d = delta-3;
+  for (; w--; from += d) {
+    *to++ = *from++;
+    *to++ = *from++;
+    *to++ = *from++;
+  }
+}
+
+static void bgr_converter(const uchar *from, uchar *to, int w, int delta) {
+  for (; w--; from += delta) {
+    uchar r = from[0];
+    uchar g = from[1];
+    *to++ = from[2];
+    *to++ = g;
+    *to++ = r;
+  }
+}
+
+static void rrr_converter(const uchar *from, uchar *to, int w, int delta) {
+  for (; w--; from += delta) {
+    *to++ = *from;
+    *to++ = *from;
+    *to++ = *from;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+// 32bit TrueColor converters on a 32 or 64-bit machine:
+
+#  ifdef U64
+#    define STORETYPE U64
+#    if WORDS_BIGENDIAN
+#      define INNARDS32(f) \
+  U64 *t = (U64*)to; \
+  int w1 = w/2; \
+  for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);} \
+  if (w&1) *t++ = (U64)(f)<<32;
+#    else
+#      define INNARDS32(f) \
+  U64 *t = (U64*)to; \
+  int w1 = w/2; \
+  for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = ((U64)(f)<<32)|i;} \
+  if (w&1) *t++ = (U64)(f);
+#    endif
+#  else
+#    define STORETYPE U32
+#    define INNARDS32(f) \
+  U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f
+#  endif
+
+static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8));
+}
+
+static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16));
+}
+
+static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2]));
+}
+
+static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24));
+}
+
+static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32(unsigned(*from) * 0x1010100U);
+}
+
+static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32(*from * 0x10101U);
+}
+
+static void
+color32_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32(
+    (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift));
+}
+
+static void
+mono32_converter(const uchar *from,uchar *to,int w, int delta) {
+  INNARDS32(
+    (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift));
+}
+
+////////////////////////////////////////////////////////////////
+
+static void figure_out_visual() {
+
+  fl_xpixel(FL_BLACK); // setup fl_redmask, etc, in fl_color.cxx
+  fl_xpixel(FL_WHITE); // also make sure white is allocated
+
+  static XPixmapFormatValues *pfvlist;
+  static int FL_NUM_pfv;
+  if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv);
+  XPixmapFormatValues *pfv;
+  for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++)
+    if (pfv->depth == fl_visual->depth) break;
+  xi.format = ZPixmap;
+  xi.byte_order = ImageByteOrder(fl_display);
+//i.bitmap_unit = 8;
+//i.bitmap_bit_order = MSBFirst;
+//i.bitmap_pad = 8;
+  xi.depth = fl_visual->depth;
+  xi.bits_per_pixel = pfv->bits_per_pixel;
+
+  if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error
+  else bytes_per_pixel = xi.bits_per_pixel/8;
+
+  unsigned int n = pfv->scanline_pad/8;
+  if (pfv->scanline_pad & 7 || (n&(n-1)))
+    Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad);
+  if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE);
+  scanline_add = n-1;
+  scanline_mask = -n;
+
+#  if USE_COLORMAP
+  if (bytes_per_pixel == 1) {
+    converter = color8_converter;
+    mono_converter = mono8_converter;
+    return;
+  }
+  if (!fl_visual->red_mask)
+    Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel);
+#  endif
+
+  // otherwise it is a TrueColor visual:
+
+  int rs = fl_redshift;
+  int gs = fl_greenshift;
+  int bs = fl_blueshift;
+
+  switch (bytes_per_pixel) {
+
+  case 2:
+    // All 16-bit TrueColor visuals are supported on any machine with
+    // 24 or more bits per integer.
+#  ifdef U16
+    xi.byte_order = WORDS_BIGENDIAN;
+#  else
+    xi.byte_order = 1;
+#  endif
+    if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) {
+      converter = c565_converter;
+      mono_converter = m565_converter;
+    } else {
+      converter = color16_converter;
+      mono_converter = mono16_converter;
+    }
+    break;
+
+  case 3:
+    if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;}
+    if (rs == 0 && gs == 8 && bs == 16) {
+      converter = rgb_converter;
+      mono_converter = rrr_converter;
+    } else if (rs == 16 && gs == 8 && bs == 0) {
+      converter = bgr_converter;
+      mono_converter = rrr_converter;
+    } else {
+      Fl::fatal("Can't do arbitrary 24bit color");
+    }
+    break;
+
+  case 4:
+    if ((xi.byte_order!=0) != WORDS_BIGENDIAN)
+      {rs = 24-rs; gs = 24-gs; bs = 24-bs;}
+    if (rs == 0 && gs == 8 && bs == 16) {
+      converter = xbgr_converter;
+      mono_converter = xrrr_converter;
+    } else if (rs == 24 && gs == 16 && bs == 8) {
+      converter = rgbx_converter;
+      mono_converter = rrrx_converter;
+    } else if (rs == 8 && gs == 16 && bs == 24) {
+      converter = bgrx_converter;
+      mono_converter = rrrx_converter;
+    } else if (rs == 16 && gs == 8 && bs == 0) {
+      converter = xrgb_converter;
+      mono_converter = xrrr_converter;
+    } else {
+      xi.byte_order = WORDS_BIGENDIAN;
+      converter = color32_converter;
+      mono_converter = mono32_converter;
+    }
+    break;
+
+  default:
+    Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel);
+  }
+
+}
+
+#  define MAXBUFFER 0x40000 // 256k
+
+static void innards(const uchar *buf, int X, int Y, int W, int H,
+		    int delta, int linedelta, int mono,
+		    Fl_Draw_Image_Cb cb, void* userdata)
+{
+  if (!linedelta) linedelta = W*delta;
+
+  int dx, dy, w, h;
+  fl_clip_box(X,Y,W,H,dx,dy,w,h);
+  if (w<=0 || h<=0) return;
+  dx -= X;
+  dy -= Y;
+
+  if (!bytes_per_pixel) figure_out_visual();
+  xi.width = w;
+  xi.height = h;
+
+  void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter;
+  if (mono) conv = mono_converter;
+
+  // See if the data is already in the right format.  Unfortunately
+  // some 32-bit x servers (XFree86) care about the unknown 8 bits
+  // and they must be zero.  I can't confirm this for user-supplied
+  // data, so the 32-bit shortcut is disabled...
+  // This can set bytes_per_line negative if image is bottom-to-top
+  // I tested it on Linux, but it may fail on other Xlib implementations:
+  if (buf && (
+#  if 0	// set this to 1 to allow 32-bit shortcut
+      delta == 4 &&
+#    if WORDS_BIGENDIAN
+      conv == rgbx_converter
+#    else
+      conv == xbgr_converter
+#    endif
+      ||
+#  endif
+      conv == rgb_converter && delta==3
+      ) && !(linedelta&scanline_add)) {
+    xi.data = (char *)(buf+delta*dx+linedelta*dy);
+    xi.bytes_per_line = linedelta;
+
+  } else {
+    int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE);
+    int blocking = h;
+    static STORETYPE *buffer;	// our storage, always word aligned
+    static long buffer_size;
+    {int size = linesize*h;
+    if (size > MAXBUFFER) {
+      size = MAXBUFFER;
+      blocking = MAXBUFFER/linesize;
+    }
+    if (size > buffer_size) {
+      delete[] buffer;
+      buffer_size = size;
+      buffer = new STORETYPE[size];
+    }}
+    xi.data = (char *)buffer;
+    xi.bytes_per_line = linesize*sizeof(STORETYPE);
+    if (buf) {
+      buf += delta*dx+linedelta*dy;
+      for (int j=0; j<h; ) {
+	STORETYPE *to = buffer;
+	int k;
+	for (k = 0; j<h && k<blocking; k++, j++) {
+	  conv(buf, (uchar*)to, w, delta);
+	  buf += linedelta;
+	  to += linesize;
+	}
+	XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k);
+      }
+    } else {
+      STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)];
+      for (int j=0; j<h; ) {
+	STORETYPE *to = buffer;
+	int k;
+	for (k = 0; j<h && k<blocking; k++, j++) {
+	  cb(userdata, dx, dy+j, w, (uchar*)linebuf);
+	  conv((uchar*)linebuf, (uchar*)to, w, delta);
+	  to += linesize;
+	}
+	XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k);
+      }
+
+      delete[] linebuf;
+    }
+  }
+}
+
+void Fl_Xlib_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_Xlib_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_Xlib_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_Xlib_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);
+}
+
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+  if (fl_visual->depth > 16) {
+    fl_color(r,g,b);
+    fl_rectf(x,y,w,h);
+  } else {
+    uchar c[3];
+    c[0] = r; c[1] = g; c[2] = b;
+    innards(c,x,y,w,h,0,0,0,0,0);
+  }
+}
+
+#endif
+
+//
+// End of "$Id: fl_draw_image.cxx 8731 2011-05-23 21:05:22Z AlbrechtS $".
+//