fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Shared_Image.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Shared_Image.cxx 7903 2010-11-28 21:06:39Z matt $"
00003 //
00004 // Shared image code for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <FL/fl_utf8.h>
00031 #include "flstring.h"
00032 
00033 #include <FL/Fl.H>
00034 #include <FL/Fl_Shared_Image.H>
00035 #include <FL/Fl_XBM_Image.H>
00036 #include <FL/Fl_XPM_Image.H>
00037 
00038 
00039 //
00040 // Global class vars...
00041 //
00042 
00043 Fl_Shared_Image **Fl_Shared_Image::images_ = 0; // Shared images
00044 int     Fl_Shared_Image::num_images_ = 0;       // Number of shared images
00045 int     Fl_Shared_Image::alloc_images_ = 0;     // Allocated shared images
00046 
00047 Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers
00048 int     Fl_Shared_Image::num_handlers_ = 0;     // Number of format handlers
00049 int     Fl_Shared_Image::alloc_handlers_ = 0;   // Allocated format handlers
00050 
00051 
00052 //
00053 // Typedef the C API sort function type the only way I know how...
00054 //
00055 
00056 extern "C" {
00057   typedef int (*compare_func_t)(const void *, const void *);
00058 }
00059 
00060 
00062 Fl_Shared_Image **Fl_Shared_Image::images() {
00063   return images_;
00064 }
00066 int Fl_Shared_Image::num_images() {
00067   return num_images_;
00068 }
00069 
00070 
00071 //
00072 // 'Fl_Shared_Image::compare()' - Compare two shared images...
00073 //
00074 
00075 int
00076 Fl_Shared_Image::compare(Fl_Shared_Image **i0,          // I - First image
00077                          Fl_Shared_Image **i1) {        // I - Second image
00078   int i = strcmp((*i0)->name(), (*i1)->name());
00079 
00080   if (i) return i;
00081   else if (((*i0)->w() == 0 && (*i1)->original_) ||
00082            ((*i1)->w() == 0 && (*i0)->original_)) return 0;
00083   else if ((*i0)->w() != (*i1)->w()) return (*i0)->w() - (*i1)->w();
00084   else return (*i0)->h() - (*i1)->h();
00085 }
00086 
00087 
00095 Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) {
00096   name_        = 0;
00097   refcount_    = 1;
00098   original_    = 0;
00099   image_       = 0;
00100   alloc_image_ = 0;
00101 }
00102 
00103 
00111 Fl_Shared_Image::Fl_Shared_Image(const char *n,         // I - Filename
00112                                  Fl_Image   *img)       // I - Image
00113   : Fl_Image(0,0,0) {
00114   name_ = new char[strlen(n) + 1];
00115   strcpy((char *)name_, n);
00116 
00117   refcount_    = 1;
00118   image_       = img;
00119   alloc_image_ = !img;
00120   original_    = 1;
00121 
00122   if (!img) reload();
00123   else update();
00124 }
00125 
00126 
00127 //
00128 // 'Fl_Shared_Image::add()' - Add a shared image to the array.
00129 //
00130 
00131 void
00132 Fl_Shared_Image::add() {
00133   Fl_Shared_Image       **temp;         // New image pointer array...
00134 
00135   if (num_images_ >= alloc_images_) {
00136     // Allocate more memory...
00137     temp = new Fl_Shared_Image *[alloc_images_ + 32];
00138 
00139     if (alloc_images_) {
00140       memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *));
00141 
00142       delete[] images_;
00143     }
00144 
00145     images_       = temp;
00146     alloc_images_ += 32;
00147   }
00148 
00149   images_[num_images_] = this;
00150   num_images_ ++;
00151 
00152   if (num_images_ > 1) {
00153     qsort(images_, num_images_, sizeof(Fl_Shared_Image *),
00154           (compare_func_t)compare);
00155   }
00156 }
00157 
00158 
00159 //
00160 // 'Fl_Shared_Image::update()' - Update the dimensions of the shared images.
00161 //
00162 
00163 void
00164 Fl_Shared_Image::update() {
00165   if (image_) {
00166     w(image_->w());
00167     h(image_->h());
00168     d(image_->d());
00169     data(image_->data(), image_->count());
00170   }
00171 }
00172 
00179 Fl_Shared_Image::~Fl_Shared_Image() {
00180   if (name_) delete[] (char *)name_;
00181   if (alloc_image_) delete image_;
00182 }
00183 
00184 
00185 //
00190 void Fl_Shared_Image::release() {
00191   int   i;      // Looping var...
00192 
00193   refcount_ --;
00194   if (refcount_ > 0) return;
00195 
00196   for (i = 0; i < num_images_; i ++)
00197     if (images_[i] == this) {
00198       num_images_ --;
00199 
00200       if (i < num_images_) {
00201         memmove(images_ + i, images_ + i + 1,
00202                (num_images_ - i) * sizeof(Fl_Shared_Image *));
00203       }
00204 
00205       break;
00206     }
00207 
00208   delete this;
00209 
00210   if (num_images_ == 0 && images_) {
00211     delete[] images_;
00212 
00213     images_       = 0;
00214     alloc_images_ = 0;
00215   }
00216 }
00217 
00218 
00219 //
00221 void Fl_Shared_Image::reload() {
00222   // Load image from disk...
00223   int           i;              // Looping var
00224   FILE          *fp;            // File pointer
00225   uchar         header[64];     // Buffer for auto-detecting files
00226   Fl_Image      *img;           // New image
00227 
00228   if (!name_) return;
00229 
00230   if ((fp = fl_fopen(name_, "rb")) != NULL) {
00231     if (fread(header, 1, sizeof(header), fp)==0) { /* ignore */ }
00232     fclose(fp);
00233   } else {
00234     return;
00235   }
00236 
00237   // Load the image as appropriate...
00238   if (memcmp(header, "#define", 7) == 0) // XBM file
00239     img = new Fl_XBM_Image(name_);
00240   else if (memcmp(header, "/* XPM */", 9) == 0) // XPM file
00241     img = new Fl_XPM_Image(name_);
00242   else {
00243     // Not a standard format; try an image handler...
00244     for (i = 0, img = 0; i < num_handlers_; i ++) {
00245       img = (handlers_[i])(name_, header, sizeof(header));
00246 
00247       if (img) break;
00248     }
00249   }
00250 
00251   if (img) {
00252     if (alloc_image_) delete image_;
00253 
00254     alloc_image_ = 1;
00255 
00256     if ((img->w() != w() && w()) || (img->h() != h() && h())) {
00257       // Make sure the reloaded image is the same size as the existing one.
00258       Fl_Image *temp = img->copy(w(), h());
00259       delete img;
00260       image_ = temp;
00261     } else {
00262       image_ = img;
00263     }
00264 
00265     update();
00266   }
00267 }
00268 
00269 
00270 //
00271 // 'Fl_Shared_Image::copy()' - Copy and resize a shared image...
00272 //
00273 
00274 Fl_Image *
00275 Fl_Shared_Image::copy(int W, int H) {
00276   Fl_Image              *temp_image;    // New image file
00277   Fl_Shared_Image       *temp_shared;   // New shared image
00278 
00279   // Make a copy of the image we're sharing...
00280   if (!image_) temp_image = 0;
00281   else temp_image = image_->copy(W, H);
00282 
00283   // Then make a new shared image...
00284   temp_shared = new Fl_Shared_Image();
00285 
00286   temp_shared->name_ = new char[strlen(name_) + 1];
00287   strcpy((char *)temp_shared->name_, name_);
00288 
00289   temp_shared->refcount_    = 1;
00290   temp_shared->image_       = temp_image;
00291   temp_shared->alloc_image_ = 1;
00292 
00293   temp_shared->update();
00294 
00295   return temp_shared;
00296 }
00297 
00298 
00299 //
00300 // 'Fl_Shared_Image::color_average()' - Blend colors...
00301 //
00302 
00303 void
00304 Fl_Shared_Image::color_average(Fl_Color c,      // I - Color to blend with
00305                                float    i) {    // I - Blend fraction
00306   if (!image_) return;
00307 
00308   image_->color_average(c, i);
00309   update();
00310 }
00311 
00312 
00313 //
00314 // 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale...
00315 //
00316 
00317 void
00318 Fl_Shared_Image::desaturate() {
00319   if (!image_) return;
00320 
00321   image_->desaturate();
00322   update();
00323 }
00324 
00325 
00326 //
00327 // 'Fl_Shared_Image::draw()' - Draw a shared image...
00328 //
00329 
00330 void
00331 Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
00332   if (image_) image_->draw(X, Y, W, H, cx, cy);
00333   else Fl_Image::draw(X, Y, W, H, cx, cy);
00334 }
00335 
00336 
00337 //
00338 // 'Fl_Shared_Image::uncache()' - Uncache the shared image...
00339 //
00340 
00341 void Fl_Shared_Image::uncache()
00342 {
00343   if (image_) image_->uncache();
00344 }
00345 
00346 
00347 
00349 Fl_Shared_Image* Fl_Shared_Image::find(const char *n, int W, int H) {
00350   Fl_Shared_Image       *key,           // Image key
00351                         **match;        // Matching image
00352 
00353   if (num_images_) {
00354     key = new Fl_Shared_Image();
00355     key->name_ = new char[strlen(n) + 1];
00356     strcpy((char *)key->name_, n);
00357     key->w(W);
00358     key->h(H);
00359 
00360     match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_,
00361                                         sizeof(Fl_Shared_Image *),
00362                                         (compare_func_t)compare);
00363 
00364     delete key;
00365 
00366     if (match) {
00367       (*match)->refcount_ ++;
00368       return *match;
00369     }
00370   }
00371 
00372   return 0;
00373 }
00374 
00375 
00383 Fl_Shared_Image* Fl_Shared_Image::get(const char *n, int W, int H) {
00384   Fl_Shared_Image       *temp;          // Image
00385 
00386   if ((temp = find(n, W, H)) != NULL) return temp;
00387 
00388   if ((temp = find(n)) == NULL) {
00389     temp = new Fl_Shared_Image(n);
00390 
00391     if (!temp->image_) {
00392       delete temp;
00393       return NULL;
00394     }
00395 
00396     temp->add();
00397   }
00398 
00399   if ((temp->w() != W || temp->h() != H) && W && H) {
00400     temp = (Fl_Shared_Image *)temp->copy(W, H);
00401     temp->add();
00402   }
00403 
00404   return temp;
00405 }
00406 
00407 
00408 
00410 void Fl_Shared_Image::add_handler(Fl_Shared_Handler f) {
00411   int                   i;              // Looping var...
00412   Fl_Shared_Handler     *temp;          // New image handler array...
00413 
00414   // First see if we have already added the handler...
00415   for (i = 0; i < num_handlers_; i ++) {
00416     if (handlers_[i] == f) return;
00417   }
00418 
00419   if (num_handlers_ >= alloc_handlers_) {
00420     // Allocate more memory...
00421     temp = new Fl_Shared_Handler [alloc_handlers_ + 32];
00422 
00423     if (alloc_handlers_) {
00424       memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler));
00425 
00426       delete[] handlers_;
00427     }
00428 
00429     handlers_       = temp;
00430     alloc_handlers_ += 32;
00431   }
00432 
00433   handlers_[num_handlers_] = f;
00434   num_handlers_ ++;
00435 }
00436 
00437 
00438 
00440 void Fl_Shared_Image::remove_handler(Fl_Shared_Handler f) {
00441   int   i;                              // Looping var...
00442 
00443   // First see if the handler has been added...
00444   for (i = 0; i < num_handlers_; i ++) {
00445     if (handlers_[i] == f) break;
00446   }
00447 
00448   if (i >= num_handlers_) return;
00449 
00450   // OK, remove the handler from the array...
00451   num_handlers_ --;
00452 
00453   if (i < num_handlers_) {
00454     // Shift later handlers down 1...
00455     memmove(handlers_ + i, handlers_ + i + 1,
00456            (num_handlers_ - i) * sizeof(Fl_Shared_Handler ));
00457   }
00458 }
00459 
00460 
00461 //
00462 // End of "$Id: Fl_Shared_Image.cxx 7903 2010-11-28 21:06:39Z matt $".
00463 //