|
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) ![]() |
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 //