PageRenderTime 26ms CodeModel.GetById 32ms RepoModel.GetById 7ms app.codeStats 0ms

/Utilities/FLTK/src/Fl_Shared_Image.cxx

https://github.com/paniwani/OTB
C++ | 467 lines | 249 code | 118 blank | 100 comment | 78 complexity | 05c0f0a211ff5891d49ded8be2ad9a82 MD5 | raw file
  1. //
  2. // "$Id$"
  3. //
  4. // Shared image code for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2005 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems on the following page:
  24. //
  25. // http://www.fltk.org/str.php
  26. //
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include "flstring.h"
  30. #include <FL/Fl.H>
  31. #include <FL/Fl_Shared_Image.H>
  32. #include <FL/Fl_XBM_Image.H>
  33. #include <FL/Fl_XPM_Image.H>
  34. //
  35. // Global class vars...
  36. //
  37. Fl_Shared_Image **Fl_Shared_Image::images_ = 0; // Shared images
  38. int Fl_Shared_Image::num_images_ = 0; // Number of shared images
  39. int Fl_Shared_Image::alloc_images_ = 0; // Allocated shared images
  40. Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers
  41. int Fl_Shared_Image::num_handlers_ = 0; // Number of format handlers
  42. int Fl_Shared_Image::alloc_handlers_ = 0; // Allocated format handlers
  43. //
  44. // Typedef the C API sort function type the only way I know how...
  45. //
  46. extern "C" {
  47. typedef int (*compare_func_t)(const void *, const void *);
  48. }
  49. // Static methods that really should be inline, but some WIN32 compilers
  50. // can't handle it...
  51. Fl_Shared_Image **Fl_Shared_Image::images() {
  52. return images_;
  53. }
  54. int Fl_Shared_Image::num_images() {
  55. return num_images_;
  56. }
  57. //
  58. // 'Fl_Shared_Image::compare()' - Compare two shared images...
  59. //
  60. int
  61. Fl_Shared_Image::compare(Fl_Shared_Image **i0, // I - First image
  62. Fl_Shared_Image **i1) { // I - Second image
  63. int i = strcmp((*i0)->name(), (*i1)->name());
  64. if (i) return i;
  65. else if (((*i0)->w() == 0 && (*i1)->original_) ||
  66. ((*i1)->w() == 0 && (*i0)->original_)) return 0;
  67. else if ((*i0)->w() != (*i1)->w()) return (*i0)->w() - (*i1)->w();
  68. else return (*i0)->h() - (*i1)->h();
  69. }
  70. //
  71. // 'Fl_Shared_Image::Fl_Shared_Image()' - Basic constructor.
  72. //
  73. Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) {
  74. name_ = 0;
  75. refcount_ = 1;
  76. original_ = 0;
  77. image_ = 0;
  78. alloc_image_ = 0;
  79. }
  80. //
  81. // 'Fl_Shared_Image::Fl_Shared_Image()' - Add an image to the image cache.
  82. //
  83. Fl_Shared_Image::Fl_Shared_Image(const char *n, // I - Filename
  84. Fl_Image *img) // I - Image
  85. : Fl_Image(0,0,0) {
  86. name_ = new char[strlen(n) + 1];
  87. strcpy((char *)name_, n);
  88. refcount_ = 1;
  89. image_ = img;
  90. alloc_image_ = !img;
  91. original_ = 1;
  92. if (!img) reload();
  93. else update();
  94. }
  95. //
  96. // 'Fl_Shared_Image::add()' - Add a shared image to the array.
  97. //
  98. void
  99. Fl_Shared_Image::add() {
  100. Fl_Shared_Image **temp; // New image pointer array...
  101. if (num_images_ >= alloc_images_) {
  102. // Allocate more memory...
  103. temp = new Fl_Shared_Image *[alloc_images_ + 32];
  104. if (alloc_images_) {
  105. memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *));
  106. delete[] images_;
  107. }
  108. images_ = temp;
  109. alloc_images_ += 32;
  110. }
  111. images_[num_images_] = this;
  112. num_images_ ++;
  113. if (num_images_ > 1) {
  114. qsort(images_, num_images_, sizeof(Fl_Shared_Image *),
  115. (compare_func_t)compare);
  116. }
  117. }
  118. //
  119. // 'Fl_Shared_Image::update()' - Update the dimensions of the shared images.
  120. //
  121. void
  122. Fl_Shared_Image::update() {
  123. if (image_) {
  124. w(image_->w());
  125. h(image_->h());
  126. d(image_->d());
  127. data(image_->data(), image_->count());
  128. }
  129. }
  130. //
  131. // 'Fl_Shared_Image::~Fl_Shared_Image()' - Destroy a shared image...
  132. //
  133. Fl_Shared_Image::~Fl_Shared_Image() {
  134. if (name_) delete[] (char *)name_;
  135. if (alloc_image_) delete image_;
  136. }
  137. //
  138. // 'Fl_Shared_Image::release()' - Release and possibly destroy a shared image.
  139. //
  140. void
  141. Fl_Shared_Image::release() {
  142. int i; // Looping var...
  143. refcount_ --;
  144. if (refcount_ > 0) return;
  145. for (i = 0; i < num_images_; i ++)
  146. if (images_[i] == this) {
  147. num_images_ --;
  148. if (i < num_images_) {
  149. memmove(images_ + i, images_ + i + 1,
  150. (num_images_ - i) * sizeof(Fl_Shared_Image *));
  151. }
  152. break;
  153. }
  154. delete this;
  155. if (num_images_ == 0 && images_) {
  156. delete[] images_;
  157. images_ = 0;
  158. alloc_images_ = 0;
  159. }
  160. }
  161. //
  162. // 'Fl_Shared_Image::reload()' - Reload the shared image...
  163. //
  164. void
  165. Fl_Shared_Image::reload() {
  166. // Load image from disk...
  167. int i; // Looping var
  168. FILE *fp; // File pointer
  169. uchar header[64]; // Buffer for auto-detecting files
  170. Fl_Image *img; // New image
  171. if (!name_) return;
  172. if ((fp = fopen(name_, "rb")) != NULL) {
  173. fread(header, 1, sizeof(header), fp);
  174. fclose(fp);
  175. } else {
  176. return;
  177. }
  178. // Load the image as appropriate...
  179. if (memcmp(header, "#define", 7) == 0) // XBM file
  180. img = new Fl_XBM_Image(name_);
  181. else if (memcmp(header, "/* XPM */", 9) == 0) // XPM file
  182. img = new Fl_XPM_Image(name_);
  183. else {
  184. // Not a standard format; try an image handler...
  185. for (i = 0, img = 0; i < num_handlers_; i ++) {
  186. img = (handlers_[i])(name_, header, sizeof(header));
  187. if (img) break;
  188. }
  189. }
  190. if (img) {
  191. if (alloc_image_) delete image_;
  192. alloc_image_ = 1;
  193. if ((img->w() != w() && w()) || (img->h() != h() && h())) {
  194. // Make sure the reloaded image is the same size as the existing one.
  195. Fl_Image *temp = img->copy(w(), h());
  196. delete img;
  197. image_ = temp;
  198. } else {
  199. image_ = img;
  200. }
  201. update();
  202. }
  203. }
  204. //
  205. // 'Fl_Shared_Image::copy()' - Copy and resize a shared image...
  206. //
  207. Fl_Image *
  208. Fl_Shared_Image::copy(int W, int H) {
  209. Fl_Image *temp_image; // New image file
  210. Fl_Shared_Image *temp_shared; // New shared image
  211. // Make a copy of the image we're sharing...
  212. if (!image_) temp_image = 0;
  213. else temp_image = image_->copy(W, H);
  214. // Then make a new shared image...
  215. temp_shared = new Fl_Shared_Image();
  216. temp_shared->name_ = new char[strlen(name_) + 1];
  217. strcpy((char *)temp_shared->name_, name_);
  218. temp_shared->refcount_ = 1;
  219. temp_shared->image_ = temp_image;
  220. temp_shared->alloc_image_ = 1;
  221. temp_shared->update();
  222. return temp_shared;
  223. }
  224. //
  225. // 'Fl_Shared_Image::color_average()' - Blend colors...
  226. //
  227. void
  228. Fl_Shared_Image::color_average(Fl_Color c, // I - Color to blend with
  229. float i) { // I - Blend fraction
  230. if (!image_) return;
  231. image_->color_average(c, i);
  232. update();
  233. }
  234. //
  235. // 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale...
  236. //
  237. void
  238. Fl_Shared_Image::desaturate() {
  239. if (!image_) return;
  240. image_->desaturate();
  241. update();
  242. }
  243. //
  244. // 'Fl_Shared_Image::draw()' - Draw a shared image...
  245. //
  246. void
  247. Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
  248. if (image_) image_->draw(X, Y, W, H, cx, cy);
  249. else Fl_Image::draw(X, Y, W, H, cx, cy);
  250. }
  251. //
  252. // 'Fl_Shared_Image::uncache()' - Uncache the shared image...
  253. //
  254. void
  255. Fl_Shared_Image::uncache()
  256. {
  257. if (image_) image_->uncache();
  258. }
  259. //
  260. // 'Fl_Shared_Image::find()' - Find a shared image...
  261. //
  262. Fl_Shared_Image *
  263. Fl_Shared_Image::find(const char *n, int W, int H) {
  264. Fl_Shared_Image *key, // Image key
  265. **match; // Matching image
  266. if (num_images_) {
  267. key = new Fl_Shared_Image();
  268. key->name_ = new char[strlen(n) + 1];
  269. strcpy((char *)key->name_, n);
  270. key->w(W);
  271. key->h(H);
  272. match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_,
  273. sizeof(Fl_Shared_Image *),
  274. (compare_func_t)compare);
  275. delete key;
  276. if (match) {
  277. (*match)->refcount_ ++;
  278. return *match;
  279. }
  280. }
  281. return 0;
  282. }
  283. //
  284. // 'Fl_Shared_Image::get()' - Get a shared image...
  285. //
  286. Fl_Shared_Image *
  287. Fl_Shared_Image::get(const char *n, int W, int H) {
  288. Fl_Shared_Image *temp; // Image
  289. if ((temp = find(n, W, H)) != NULL) return temp;
  290. if ((temp = find(n)) == NULL) {
  291. temp = new Fl_Shared_Image(n);
  292. if (!temp->image_) {
  293. delete temp;
  294. return NULL;
  295. }
  296. temp->add();
  297. }
  298. if ((temp->w() != W || temp->h() != H) && W && H) {
  299. temp = (Fl_Shared_Image *)temp->copy(W, H);
  300. temp->add();
  301. }
  302. return temp;
  303. }
  304. //
  305. // 'Fl_Shared_Image::add_handler()' - Add a shared image handler.
  306. //
  307. void
  308. Fl_Shared_Image::add_handler(Fl_Shared_Handler f) {
  309. int i; // Looping var...
  310. Fl_Shared_Handler *temp; // New image handler array...
  311. // First see if we have already added the handler...
  312. for (i = 0; i < num_handlers_; i ++) {
  313. if (handlers_[i] == f) return;
  314. }
  315. if (num_handlers_ >= alloc_handlers_) {
  316. // Allocate more memory...
  317. temp = new Fl_Shared_Handler [alloc_handlers_ + 32];
  318. if (alloc_handlers_) {
  319. memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler));
  320. delete[] handlers_;
  321. }
  322. handlers_ = temp;
  323. alloc_handlers_ += 32;
  324. }
  325. handlers_[num_handlers_] = f;
  326. num_handlers_ ++;
  327. }
  328. //
  329. // 'Fl_Shared_Image::remove_handler()' - Remove a shared image handler.
  330. //
  331. void
  332. Fl_Shared_Image::remove_handler(Fl_Shared_Handler f) {
  333. int i; // Looping var...
  334. // First see if the handler has been added...
  335. for (i = 0; i < num_handlers_; i ++) {
  336. if (handlers_[i] == f) break;
  337. }
  338. if (i >= num_handlers_) return;
  339. // OK, remove the handler from the array...
  340. num_handlers_ --;
  341. if (i < num_handlers_) {
  342. // Shift later handlers down 1...
  343. memmove(handlers_ + i, handlers_ + i + 1,
  344. (num_handlers_ - i) * sizeof(Fl_Shared_Handler ));
  345. }
  346. }
  347. //
  348. // End of "$Id$".
  349. //