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_Shared_Image.cxx b/common/fltk/src/Fl_Shared_Image.cxx
new file mode 100644
index 0000000..13598a9
--- /dev/null
+++ b/common/fltk/src/Fl_Shared_Image.cxx
@@ -0,0 +1,476 @@
+//
+// "$Id: Fl_Shared_Image.cxx 8306 2011-01-24 17:04:22Z matt $"
+//
+// Shared image code 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
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <FL/fl_utf8.h>
+#include "flstring.h"
+
+#include <FL/Fl.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl_XBM_Image.H>
+#include <FL/Fl_XPM_Image.H>
+
+
+//
+// Global class vars...
+//
+
+Fl_Shared_Image **Fl_Shared_Image::images_ = 0;	// Shared images
+int	Fl_Shared_Image::num_images_ = 0;	// Number of shared images
+int	Fl_Shared_Image::alloc_images_ = 0;	// Allocated shared images
+
+Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers
+int	Fl_Shared_Image::num_handlers_ = 0;	// Number of format handlers
+int	Fl_Shared_Image::alloc_handlers_ = 0;	// Allocated format handlers
+
+
+//
+// Typedef the C API sort function type the only way I know how...
+//
+
+extern "C" {
+  typedef int (*compare_func_t)(const void *, const void *);
+}
+
+
+/** Returns the Fl_Shared_Image* array */
+Fl_Shared_Image **Fl_Shared_Image::images() {
+  return images_;
+}
+/** Returns the total number of shared images in the array. */
+int Fl_Shared_Image::num_images() {
+  return num_images_;
+}
+
+
+//
+// 'Fl_Shared_Image::compare()' - Compare two shared images...
+//
+
+int
+Fl_Shared_Image::compare(Fl_Shared_Image **i0,		// I - First image
+                         Fl_Shared_Image **i1) {	// I - Second image
+  int i = strcmp((*i0)->name(), (*i1)->name());
+
+  if (i) return i;
+  else if (((*i0)->w() == 0 && (*i1)->original_) ||
+           ((*i1)->w() == 0 && (*i0)->original_)) return 0;
+  else if ((*i0)->w() != (*i1)->w()) return (*i0)->w() - (*i1)->w();
+  else return (*i0)->h() - (*i1)->h();
+}
+
+
+/** 
+  Creates an empty shared image.
+  The constructors create a new shared image record in the image cache.
+  
+  <P>The constructors are protected and cannot be used directly
+  from a program. Use the get() method instead.
+*/
+Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) {
+  name_        = 0;
+  refcount_    = 1;
+  original_    = 0;
+  image_       = 0;
+  alloc_image_ = 0;
+}
+
+
+/** 
+  Creates a shared image from its filename and its corresponding Fl_Image* img.
+  The constructors create a new shared image record in the image cache.
+  
+  <P>The constructors are protected and cannot be used directly
+  from a program. Use the get() method instead.
+*/
+Fl_Shared_Image::Fl_Shared_Image(const char *n,		// I - Filename
+                                 Fl_Image   *img)	// I - Image
+  : Fl_Image(0,0,0) {
+  name_ = new char[strlen(n) + 1];
+  strcpy((char *)name_, n);
+
+  refcount_    = 1;
+  image_       = img;
+  alloc_image_ = !img;
+  original_    = 1;
+
+  if (!img) reload();
+  else update();
+}
+
+
+//
+// 'Fl_Shared_Image::add()' - Add a shared image to the array.
+//
+
+void
+Fl_Shared_Image::add() {
+  Fl_Shared_Image	**temp;		// New image pointer array...
+
+  if (num_images_ >= alloc_images_) {
+    // Allocate more memory...
+    temp = new Fl_Shared_Image *[alloc_images_ + 32];
+
+    if (alloc_images_) {
+      memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *));
+
+      delete[] images_;
+    }
+
+    images_       = temp;
+    alloc_images_ += 32;
+  }
+
+  images_[num_images_] = this;
+  num_images_ ++;
+
+  if (num_images_ > 1) {
+    qsort(images_, num_images_, sizeof(Fl_Shared_Image *),
+          (compare_func_t)compare);
+  }
+}
+
+
+//
+// 'Fl_Shared_Image::update()' - Update the dimensions of the shared images.
+//
+
+void
+Fl_Shared_Image::update() {
+  if (image_) {
+    w(image_->w());
+    h(image_->h());
+    d(image_->d());
+    data(image_->data(), image_->count());
+  }
+}
+
+/**
+  The destructor free all memory and server resources that are
+  used by the image. The destructor is protected and cannot be
+  used directly from a program. Use the Fl_Shared_Image::release() method
+  instead.
+*/
+Fl_Shared_Image::~Fl_Shared_Image() {
+  if (name_) delete[] (char *)name_;
+  if (alloc_image_) delete image_;
+}
+
+
+//
+/** 
+  Releases and possibly destroys (if refcount <=0) a shared image. 
+  In the latter case, it will reorganize the shared image array so that no hole will occur.
+*/
+void Fl_Shared_Image::release() {
+  int	i;	// Looping var...
+
+  refcount_ --;
+  if (refcount_ > 0) return;
+
+  for (i = 0; i < num_images_; i ++)
+    if (images_[i] == this) {
+      num_images_ --;
+
+      if (i < num_images_) {
+        memmove(images_ + i, images_ + i + 1,
+               (num_images_ - i) * sizeof(Fl_Shared_Image *));
+      }
+
+      break;
+    }
+
+  delete this;
+
+  if (num_images_ == 0 && images_) {
+    delete[] images_;
+
+    images_       = 0;
+    alloc_images_ = 0;
+  }
+}
+
+
+//
+/** Reloads the shared image from disk */
+void Fl_Shared_Image::reload() {
+  // Load image from disk...
+  int		i;		// Looping var
+  FILE		*fp;		// File pointer
+  uchar		header[64];	// Buffer for auto-detecting files
+  Fl_Image	*img;		// New image
+
+  if (!name_) return;
+
+  if ((fp = fl_fopen(name_, "rb")) != NULL) {
+    if (fread(header, 1, sizeof(header), fp)==0) { /* ignore */ }
+    fclose(fp);
+  } else {
+    return;
+  }
+
+  // Load the image as appropriate...
+  if (memcmp(header, "#define", 7) == 0) // XBM file
+    img = new Fl_XBM_Image(name_);
+  else if (memcmp(header, "/* XPM */", 9) == 0) // XPM file
+    img = new Fl_XPM_Image(name_);
+  else {
+    // Not a standard format; try an image handler...
+    for (i = 0, img = 0; i < num_handlers_; i ++) {
+      img = (handlers_[i])(name_, header, sizeof(header));
+
+      if (img) break;
+    }
+  }
+
+  if (img) {
+    if (alloc_image_) delete image_;
+
+    alloc_image_ = 1;
+
+    if ((img->w() != w() && w()) || (img->h() != h() && h())) {
+      // Make sure the reloaded image is the same size as the existing one.
+      Fl_Image *temp = img->copy(w(), h());
+      delete img;
+      image_ = temp;
+    } else {
+      image_ = img;
+    }
+
+    update();
+  }
+}
+
+
+//
+// 'Fl_Shared_Image::copy()' - Copy and resize a shared image...
+//
+
+Fl_Image *
+Fl_Shared_Image::copy(int W, int H) {
+  Fl_Image		*temp_image;	// New image file
+  Fl_Shared_Image	*temp_shared;	// New shared image
+
+  // Make a copy of the image we're sharing...
+  if (!image_) temp_image = 0;
+  else temp_image = image_->copy(W, H);
+
+  // Then make a new shared image...
+  temp_shared = new Fl_Shared_Image();
+
+  temp_shared->name_ = new char[strlen(name_) + 1];
+  strcpy((char *)temp_shared->name_, name_);
+
+  temp_shared->refcount_    = 1;
+  temp_shared->image_       = temp_image;
+  temp_shared->alloc_image_ = 1;
+
+  temp_shared->update();
+
+  return temp_shared;
+}
+
+
+//
+// 'Fl_Shared_Image::color_average()' - Blend colors...
+//
+
+void
+Fl_Shared_Image::color_average(Fl_Color c,	// I - Color to blend with
+                               float    i) {	// I - Blend fraction
+  if (!image_) return;
+
+  image_->color_average(c, i);
+  update();
+}
+
+
+//
+// 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale...
+//
+
+void
+Fl_Shared_Image::desaturate() {
+  if (!image_) return;
+
+  image_->desaturate();
+  update();
+}
+
+
+//
+// 'Fl_Shared_Image::draw()' - Draw a shared image...
+//
+
+void
+Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
+  if (image_) image_->draw(X, Y, W, H, cx, cy);
+  else Fl_Image::draw(X, Y, W, H, cx, cy);
+}
+
+
+//
+// 'Fl_Shared_Image::uncache()' - Uncache the shared image...
+//
+
+void Fl_Shared_Image::uncache()
+{
+  if (image_) image_->uncache();
+}
+
+
+
+/** Finds a shared image from its named and size specifications */
+Fl_Shared_Image* Fl_Shared_Image::find(const char *n, int W, int H) {
+  Fl_Shared_Image	*key,		// Image key
+			**match;	// Matching image
+
+  if (num_images_) {
+    key = new Fl_Shared_Image();
+    key->name_ = new char[strlen(n) + 1];
+    strcpy((char *)key->name_, n);
+    key->w(W);
+    key->h(H);
+
+    match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_,
+                                        sizeof(Fl_Shared_Image *),
+                                        (compare_func_t)compare);
+
+    delete key;
+
+    if (match) {
+      (*match)->refcount_ ++;
+      return *match;
+    }
+  }
+
+  return 0;
+}
+
+
+/** 
+ \brief Find or load an image that can be shared by multiple widgets.
+ 
+ Gets a shared image, if it exists already ; it will return it.
+ If it does not exist or if it exist but with other size, 
+ then the existing image is deleted and replaced
+ by a new image from the n filename of the proper dimension.
+ If n is not a valid image filename, then get() will return NULL.
+ 
+ Shared JPEG and PNG images can also be created from memory by using their 
+ named memory access constructor.
+ 
+ \param n name of the image
+ \param W, H desired size
+ 
+ \see Fl_Shared_Image::find(const char *n, int W, int H)
+ \see Fl_Shared_Image::release() 
+ \see Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data)
+ \see Fl_PNG_Image::Fl_PNG_Image (const char *name_png, const unsigned char *buffer, int maxsize)
+*/
+Fl_Shared_Image* Fl_Shared_Image::get(const char *n, int W, int H) {
+  Fl_Shared_Image	*temp;		// Image
+
+  if ((temp = find(n, W, H)) != NULL) return temp;
+
+  if ((temp = find(n)) == NULL) {
+    temp = new Fl_Shared_Image(n);
+
+    if (!temp->image_) {
+      delete temp;
+      return NULL;
+    }
+
+    temp->add();
+  }
+
+  if ((temp->w() != W || temp->h() != H) && W && H) {
+    temp = (Fl_Shared_Image *)temp->copy(W, H);
+    temp->add();
+  }
+
+  return temp;
+}
+
+
+
+/** Adds a shared image handler, which is basically a test function for adding new formats */
+void Fl_Shared_Image::add_handler(Fl_Shared_Handler f) {
+  int			i;		// Looping var...
+  Fl_Shared_Handler	*temp;		// New image handler array...
+
+  // First see if we have already added the handler...
+  for (i = 0; i < num_handlers_; i ++) {
+    if (handlers_[i] == f) return;
+  }
+
+  if (num_handlers_ >= alloc_handlers_) {
+    // Allocate more memory...
+    temp = new Fl_Shared_Handler [alloc_handlers_ + 32];
+
+    if (alloc_handlers_) {
+      memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler));
+
+      delete[] handlers_;
+    }
+
+    handlers_       = temp;
+    alloc_handlers_ += 32;
+  }
+
+  handlers_[num_handlers_] = f;
+  num_handlers_ ++;
+}
+
+
+
+/** Removes a shared image handler */
+void Fl_Shared_Image::remove_handler(Fl_Shared_Handler f) {
+  int	i;				// Looping var...
+
+  // First see if the handler has been added...
+  for (i = 0; i < num_handlers_; i ++) {
+    if (handlers_[i] == f) break;
+  }
+
+  if (i >= num_handlers_) return;
+
+  // OK, remove the handler from the array...
+  num_handlers_ --;
+
+  if (i < num_handlers_) {
+    // Shift later handlers down 1...
+    memmove(handlers_ + i, handlers_ + i + 1,
+           (num_handlers_ - i) * sizeof(Fl_Shared_Handler ));
+  }
+}
+
+
+//
+// End of "$Id: Fl_Shared_Image.cxx 8306 2011-01-24 17:04:22Z matt $".
+//