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

Fl_Shared_Image.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Shared image code for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2016 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <FL/fl_utf8.h>
22 #include "flstring.h"
23 
24 #include <FL/Fl.H>
25 #include <FL/Fl_Shared_Image.H>
26 #include <FL/Fl_XBM_Image.H>
27 #include <FL/Fl_XPM_Image.H>
28 #include <FL/Fl_Preferences.H>
29 #include <FL/fl_draw.H>
30 
31 //
32 // Global class vars...
33 //
34 
35 Fl_Shared_Image **Fl_Shared_Image::images_ = 0; // Shared images
36 int Fl_Shared_Image::num_images_ = 0; // Number of shared images
37 int Fl_Shared_Image::alloc_images_ = 0; // Allocated shared images
38 
39 Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers
40 int Fl_Shared_Image::num_handlers_ = 0; // Number of format handlers
41 int Fl_Shared_Image::alloc_handlers_ = 0; // Allocated format handlers
42 
43 
44 //
45 // Typedef the C API sort function type the only way I know how...
46 //
47 
48 extern "C" {
49  typedef int (*compare_func_t)(const void *, const void *);
50 }
51 
52 
55  return images_;
56 }
57 
58 
61  return num_images_;
62 }
63 
64 
100 int
102  Fl_Shared_Image **i1) { // I - Second image
103  int i = strcmp((*i0)->name(), (*i1)->name());
104 
105  if (i) return i;
106  else if (((*i0)->w() == 0 && (*i1)->original_) ||
107  ((*i1)->w() == 0 && (*i0)->original_)) return 0;
108  else if ((*i0)->w() != (*i1)->w()) return (*i0)->w() - (*i1)->w();
109  else return (*i0)->h() - (*i1)->h();
110 }
111 
112 
121  name_ = 0;
122  refcount_ = 1;
123  original_ = 0;
124  image_ = 0;
125  alloc_image_ = 0;
126 #if FLTK_ABI_VERSION >= 10304
127  scaled_image_= 0;
128 #endif
129 }
130 
131 
139 Fl_Shared_Image::Fl_Shared_Image(const char *n, // I - Filename
140  Fl_Image *img) // I - Image
141  : Fl_Image(0,0,0) {
142  name_ = new char[strlen(n) + 1];
143  strcpy((char *)name_, n);
144 
145  refcount_ = 1;
146  image_ = img;
147  alloc_image_ = !img;
148  original_ = 1;
149 #if FLTK_ABI_VERSION >= 10304
150  scaled_image_= 0;
151 #endif
152 
153  if (!img) reload();
154  else update();
155 }
156 
157 
166 void
168  Fl_Shared_Image **temp; // New image pointer array...
169 
170  if (num_images_ >= alloc_images_) {
171  // Allocate more memory...
172  temp = new Fl_Shared_Image *[alloc_images_ + 32];
173 
174  if (alloc_images_) {
175  memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *));
176 
177  delete[] images_;
178  }
179 
180  images_ = temp;
181  alloc_images_ += 32;
182  }
183 
184  images_[num_images_] = this;
185  num_images_ ++;
186 
187  if (num_images_ > 1) {
188  qsort(images_, num_images_, sizeof(Fl_Shared_Image *),
190  }
191 }
192 
193 
194 //
195 // 'Fl_Shared_Image::update()' - Update the dimensions of the shared images.
196 //
197 
198 void
200  if (image_) {
201  w(image_->w());
202  h(image_->h());
203  d(image_->d());
204  data(image_->data(), image_->count());
205  }
206 }
207 
216  if (name_) delete[] (char *)name_;
217  if (alloc_image_) delete image_;
218 #if FLTK_ABI_VERSION >= 10304
219  delete scaled_image_;
220 #endif
221 }
222 
223 
231  int i; // Looping var...
232 
233  refcount_ --;
234  if (refcount_ > 0) return;
235 
236  for (i = 0; i < num_images_; i ++)
237  if (images_[i] == this) {
238  num_images_ --;
239 
240  if (i < num_images_) {
241  memmove(images_ + i, images_ + i + 1,
242  (num_images_ - i) * sizeof(Fl_Shared_Image *));
243  }
244 
245  break;
246  }
247 
248  delete this;
249 
250  if (num_images_ == 0 && images_) {
251  delete[] images_;
252 
253  images_ = 0;
254  alloc_images_ = 0;
255  }
256 }
257 
258 
261  // Load image from disk...
262  int i; // Looping var
263  FILE *fp; // File pointer
264  uchar header[64]; // Buffer for auto-detecting files
265  Fl_Image *img; // New image
266 
267  if (!name_) return;
268 
269  if ((fp = fl_fopen(name_, "rb")) != NULL) {
270  if (fread(header, 1, sizeof(header), fp)==0) { /* ignore */ }
271  fclose(fp);
272  } else {
273  return;
274  }
275 
276  // Load the image as appropriate...
277  if (memcmp(header, "#define", 7) == 0) // XBM file
278  img = new Fl_XBM_Image(name_);
279  else if (memcmp(header, "/* XPM */", 9) == 0) // XPM file
280  img = new Fl_XPM_Image(name_);
281  else {
282  // Not a standard format; try an image handler...
283  for (i = 0, img = 0; i < num_handlers_; i ++) {
284  img = (handlers_[i])(name_, header, sizeof(header));
285 
286  if (img) break;
287  }
288  }
289 
290  if (img) {
291  if (alloc_image_) delete image_;
292 
293  alloc_image_ = 1;
294 
295  if ((img->w() != w() && w()) || (img->h() != h() && h())) {
296  // Make sure the reloaded image is the same size as the existing one.
297  Fl_Image *temp = img->copy(w(), h());
298  delete img;
299  image_ = temp;
300  } else {
301  image_ = img;
302  }
303 
304  update();
305  }
306 }
307 
308 
309 //
310 // 'Fl_Shared_Image::copy()' - Copy and resize a shared image...
311 //
312 // Note: intentionally no doxygen docs here.
313 // For doxygen docs see Fl_Image::copy().
314 
315 Fl_Image *
317  Fl_Image *temp_image; // New image file
318  Fl_Shared_Image *temp_shared; // New shared image
319 
320  // Make a copy of the image we're sharing...
321  if (!image_) temp_image = 0;
322  else temp_image = image_->copy(W, H);
323 
324  // Then make a new shared image...
325  temp_shared = new Fl_Shared_Image();
326 
327  temp_shared->name_ = new char[strlen(name_) + 1];
328  strcpy((char *)temp_shared->name_, name_);
329 
330  temp_shared->refcount_ = 1;
331  temp_shared->image_ = temp_image;
332  temp_shared->alloc_image_ = 1;
333 
334  temp_shared->update();
335 
336  return temp_shared;
337 }
338 
339 
340 //
341 // 'Fl_Shared_Image::color_average()' - Blend colors...
342 //
343 
344 void
345 Fl_Shared_Image::color_average(Fl_Color c, // I - Color to blend with
346  float i) { // I - Blend fraction
347  if (!image_) return;
348 
349  image_->color_average(c, i);
350  update();
351 }
352 
353 
354 //
355 // 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale...
356 //
357 
358 void
360  if (!image_) return;
361 
362  image_->desaturate();
363  update();
364 }
365 
366 
367 //
368 // 'Fl_Shared_Image::draw()' - Draw a shared image...
369 //
370 void Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
371 #if FLTK_ABI_VERSION >= 10304
372  if (!image_) {
373  Fl_Image::draw(X, Y, W, H, cx, cy);
374  return;
375  }
376  if (w() == image_->w() && h() == image_->h()) {
377  image_->draw(X, Y, W, H, cx, cy);
378  return;
379  }
380  fl_push_clip(X, Y, W, H);
381  int done = 0;
382  // don't call Fl_Graphics_Driver::draw_scaled(Fl_Image*,...) for an enlarged Fl_Bitmap or Fl_Pixmap
383  if ((d() != 0 && count() < 2) || (w() <= image_->w() && h() <= image_->h())) {
384  done = fl_graphics_driver->draw_scaled(image_, X-cx, Y-cy, w(), h());
385  }
386  if (!done) {
387  if (scaled_image_ && (scaled_image_->w() != w() || scaled_image_->h() != h())) {
388  delete scaled_image_;
389  scaled_image_ = NULL;
390  }
391  if (!scaled_image_) {
392  Fl_RGB_Scaling previous = RGB_scaling();
393  RGB_scaling(scaling_algorithm_); // useless but no harm if image_ is not an Fl_RGB_Image
394  scaled_image_ = image_->copy(w(), h());
395  RGB_scaling(previous);
396  }
397  scaled_image_->draw(X-cx, Y-cy, scaled_image_->w(), scaled_image_->h(), 0, 0);
398  }
399  fl_pop_clip();
400 #else
401  if (image_) image_->draw(X, Y, W, H, cx, cy);
402  else Fl_Image::draw(X, Y, W, H, cx, cy);
403 #endif // FLTK_ABI_VERSION
404 }
405 
429 void Fl_Shared_Image::scale(int width, int height, int proportional, int can_expand)
430 {
431 #if FLTK_ABI_VERSION >= 10304
432  w(width);
433  h(height);
434  if (!image_) return;
435  float fw = image_->w() / float(width);
436  float fh = image_->h() / float(height);
437  if (proportional) {
438  if (fh > fw) fw = fh;
439  else fh = fw;
440  }
441  if (!can_expand) {
442  if (fw < 1) fw = 1;
443  if (fh < 1) fh = 1;
444  }
445  w(int(image_->w() / fw));
446  h(int(image_->h() / fh));
447 #endif
448 }
449 
450 
452 
453 
454 //
455 // 'Fl_Shared_Image::uncache()' - Uncache the shared image...
456 //
457 
459 {
460  if (image_) image_->uncache();
461 }
462 
463 
464 
479 Fl_Shared_Image* Fl_Shared_Image::find(const char *name, int W, int H) {
480  Fl_Shared_Image *key, // Image key
481  **match; // Matching image
482 
483  if (num_images_) {
484  key = new Fl_Shared_Image();
485  key->name_ = new char[strlen(name) + 1];
486  strcpy((char *)key->name_, name);
487  key->w(W);
488  key->h(H);
489 
490  match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_,
491  sizeof(Fl_Shared_Image *),
493 
494  delete key;
495 
496  if (match) {
497  (*match)->refcount_ ++;
498  return *match;
499  }
500  }
501 
502  return 0;
503 }
504 
505 
541 Fl_Shared_Image* Fl_Shared_Image::get(const char *name, int W, int H) {
542  Fl_Shared_Image *temp; // Image
543 
544  if ((temp = find(name, W, H)) != NULL) return temp;
545 
546  if ((temp = find(name)) == NULL) {
547  temp = new Fl_Shared_Image(name);
548 
549  if (!temp->image_) {
550  delete temp;
551  return NULL;
552  }
553 
554  temp->add();
555  }
556 
557  if ((temp->w() != W || temp->h() != H) && W && H) {
558  temp = (Fl_Shared_Image *)temp->copy(W, H);
559  temp->add();
560  }
561 
562  return temp;
563 }
564 
574 {
576  shared->alloc_image_ = own_it;
577  shared->add();
578  return shared;
579 }
580 
581 
586  int i; // Looping var...
587  Fl_Shared_Handler *temp; // New image handler array...
588 
589  // First see if we have already added the handler...
590  for (i = 0; i < num_handlers_; i ++) {
591  if (handlers_[i] == f) return;
592  }
593 
595  // Allocate more memory...
596  temp = new Fl_Shared_Handler [alloc_handlers_ + 32];
597 
598  if (alloc_handlers_) {
599  memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler));
600 
601  delete[] handlers_;
602  }
603 
604  handlers_ = temp;
605  alloc_handlers_ += 32;
606  }
607 
609  num_handlers_ ++;
610 }
611 
612 
615  int i; // Looping var...
616 
617  // First see if the handler has been added...
618  for (i = 0; i < num_handlers_; i ++) {
619  if (handlers_[i] == f) break;
620  }
621 
622  if (i >= num_handlers_) return;
623 
624  // OK, remove the handler from the array...
625  num_handlers_ --;
626 
627  if (i < num_handlers_) {
628  // Shift later handlers down 1...
629  memmove(handlers_ + i, handlers_ + i + 1,
630  (num_handlers_ - i) * sizeof(Fl_Shared_Handler ));
631  }
632 }
633 
634 
635 //
636 // End of "$Id$".
637 //
Fl_Image::d
void d(int D)
Definition: Fl_Image.H:84
Fl_Shared_Image::original_
int original_
Definition: Fl_Shared_Image.H:70
Fl.H
Fl_Shared_Image::image_
Fl_Image * image_
Definition: Fl_Shared_Image.H:72
Fl_Graphics_Driver::draw_scaled
int draw_scaled(Fl_Image *img, int X, int Y, int W, int H)
Definition: Fl_Image.cxx:674
Fl_Color
unsigned int Fl_Color
Definition: Enumerations.H:934
Fl_Image::data
void data(const char *const *p, int c)
Definition: Fl_Image.H:100
Fl_Image::data
const char *const * data() const
Definition: Fl_Image.H:138
Fl_Image::h
void h(int H)
Definition: Fl_Image.H:80
Fl_Image::d
int d() const
Definition: Fl_Image.H:121
Fl_Image
Base class for image caching and drawing.
Definition: Fl_Image.H:55
Fl_Shared_Image::num_images
static int num_images()
Definition: Fl_Shared_Image.cxx:60
Fl_Shared_Image::copy
virtual Fl_Image * copy(int W, int H)
Definition: Fl_Shared_Image.cxx:316
compare_func_t
int(* compare_func_t)(const void *, const void *)
Definition: Fl_Shared_Image.cxx:49
Fl_Image::count
int count() const
Definition: Fl_Image.H:133
Fl_Image::uncache
virtual void uncache()
Definition: Fl_Image.cxx:63
Fl_RGB_Scaling
Fl_RGB_Scaling
Definition: Fl_Image.H:37
Fl_Shared_Image::alloc_handlers_
static int alloc_handlers_
Definition: Fl_Shared_Image.H:67
Fl_XPM_Image.H
Fl_Shared_Image::Fl_Shared_Image
Fl_Shared_Image()
Definition: Fl_Shared_Image.cxx:120
H
static int H
Definition: Fl_Tooltip.cxx:76
Fl_Shared_Image::draw
virtual void draw(int X, int Y, int W, int H, int cx, int cy)
Definition: Fl_Shared_Image.cxx:370
NULL
#define NULL
Definition: forms.H:34
Fl_Shared_Image::color_average
virtual void color_average(Fl_Color c, float i)
Definition: Fl_Shared_Image.cxx:345
Fl_Shared_Image::num_images_
static int num_images_
Definition: Fl_Shared_Image.H:63
Fl_Image::w
void w(int W)
Definition: Fl_Image.H:76
fl_fopen
FILE * fl_fopen(const char *f, const char *mode)
Definition: fl_utf8.cxx:498
Fl_Shared_Image::alloc_images_
static int alloc_images_
Definition: Fl_Shared_Image.H:64
Fl_Shared_Image::name
const char * name()
Definition: Fl_Shared_Image.H:86
key
int key
Definition: Fl_Text_Editor.cxx:91
Fl_Shared_Image::uncache
virtual void uncache()
Definition: Fl_Shared_Image.cxx:458
Fl_Shared_Image::alloc_image_
int alloc_image_
Definition: Fl_Shared_Image.H:73
Fl_Image::color_average
virtual void color_average(Fl_Color c, float i)
Definition: Fl_Image.cxx:106
Fl_Shared_Image::name_
const char * name_
Definition: Fl_Shared_Image.H:69
fl_utf8.h
header for Unicode and UTF-8 character handling
fl_draw.H
utility header to pull drawing functions together
Fl_Shared_Image::scale
void scale(int width, int height, int proportional=1, int can_expand=0)
Definition: Fl_Shared_Image.cxx:429
Fl_Shared_Image::find
static Fl_Shared_Image * find(const char *name, int W=0, int H=0)
Definition: Fl_Shared_Image.cxx:479
Fl_Shared_Image::add
void add()
Definition: Fl_Shared_Image.cxx:167
Fl_Shared_Image::refcount_
int refcount_
Definition: Fl_Shared_Image.H:71
Fl_Image::h
int h() const
Definition: Fl_Image.H:115
Fl_Shared_Image::reload
void reload()
Definition: Fl_Shared_Image.cxx:260
Fl_Shared_Image::add_handler
static void add_handler(Fl_Shared_Handler f)
Definition: Fl_Shared_Image.cxx:585
Fl_Shared_Image::copy
Fl_Image * copy()
Definition: Fl_Shared_Image.H:106
fl_push_clip
void fl_push_clip(int x, int y, int w, int h)
Definition: fl_draw.H:82
Fl_Image::RGB_scaling
static Fl_RGB_Scaling RGB_scaling()
Definition: Fl_Image.cxx:226
Fl_Shared_Image::images
static Fl_Shared_Image ** images()
Definition: Fl_Shared_Image.cxx:54
Fl_Image::copy
virtual Fl_Image * copy(int W, int H)
Definition: Fl_Image.cxx:91
fl_graphics_driver
FL_EXPORT Fl_Graphics_Driver * fl_graphics_driver
Points to the driver that currently receives all graphics requests.
Definition: Fl_Device.cxx:50
Fl_Preferences::newUUID
static const char * newUUID()
Definition: Fl_Preferences.cxx:82
Fl_Shared_Image.H
Fl_XPM_Image
Definition: Fl_XPM_Image.H:31
fl_pop_clip
void fl_pop_clip()
Definition: fl_draw.H:103
Fl_Shared_Image::get
static Fl_Shared_Image * get(const char *name, int W=0, int H=0)
Definition: Fl_Shared_Image.cxx:541
Fl_Shared_Image::update
void update()
Definition: Fl_Shared_Image.cxx:199
Fl_Image::draw
virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0)
Definition: Fl_Image.cxx:66
Fl_XBM_Image
Definition: Fl_XBM_Image.H:30
Fl_Shared_Image::images_
static Fl_Shared_Image ** images_
Definition: Fl_Shared_Image.H:62
Fl_XBM_Image.H
Fl_Shared_Image::desaturate
virtual void desaturate()
Definition: Fl_Shared_Image.cxx:359
FL_RGB_SCALING_BILINEAR
more accurate, but slower RGB image scaling algorithm
Definition: Fl_Image.H:39
Fl_Image::w
int w() const
Definition: Fl_Image.H:111
Fl_Shared_Image::remove_handler
static void remove_handler(Fl_Shared_Handler f)
Definition: Fl_Shared_Image.cxx:614
Fl_Shared_Image::compare
static int compare(Fl_Shared_Image **i0, Fl_Shared_Image **i1)
Definition: Fl_Shared_Image.cxx:101
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
Y
static int Y
Definition: Fl_Tooltip.cxx:76
flstring.h
Fl_Shared_Image::~Fl_Shared_Image
virtual ~Fl_Shared_Image()
Definition: Fl_Shared_Image.cxx:215
Fl_Shared_Handler
Fl_Image *(* Fl_Shared_Handler)(const char *name, uchar *header, int headerlen)
Definition: Fl_Shared_Image.H:29
Fl_Preferences.H
Fl_Shared_Image::scaling_algorithm_
static Fl_RGB_Scaling scaling_algorithm_
Definition: Fl_Shared_Image.H:56
uchar
unsigned char uchar
Definition: fl_types.h:30
name
static const char * name
Definition: Fl_arg.cxx:53
Fl_RGB_Image
Definition: Fl_Image.H:202
Fl_Shared_Image
Definition: Fl_Shared_Image.H:50
Fl_Image::desaturate
virtual void desaturate()
Definition: Fl_Image.cxx:117
Fl_Shared_Image::release
void release()
Definition: Fl_Shared_Image.cxx:230
Fl_Shared_Image::num_handlers_
static int num_handlers_
Definition: Fl_Shared_Image.H:66
Fl_Shared_Image::handlers_
static Fl_Shared_Handler * handlers_
Definition: Fl_Shared_Image.H:65