2 // "$Id: Fl_Shared_Image.cxx 8306 2011-01-24 17:04:22Z matt $"
4 // Shared image code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
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.
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.
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
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
30 #include <FL/fl_utf8.h>
34 #include <FL/Fl_Shared_Image.H>
35 #include <FL/Fl_XBM_Image.H>
36 #include <FL/Fl_XPM_Image.H>
40 // Global class vars...
43 Fl_Shared_Image
**Fl_Shared_Image::images_
= 0; // Shared images
44 int Fl_Shared_Image::num_images_
= 0; // Number of shared images
45 int Fl_Shared_Image::alloc_images_
= 0; // Allocated shared images
47 Fl_Shared_Handler
*Fl_Shared_Image::handlers_
= 0;// Additional format handlers
48 int Fl_Shared_Image::num_handlers_
= 0; // Number of format handlers
49 int Fl_Shared_Image::alloc_handlers_
= 0; // Allocated format handlers
53 // Typedef the C API sort function type the only way I know how...
57 typedef int (*compare_func_t
)(const void *, const void *);
61 /** Returns the Fl_Shared_Image* array */
62 Fl_Shared_Image
**Fl_Shared_Image::images() {
65 /** Returns the total number of shared images in the array. */
66 int Fl_Shared_Image::num_images() {
72 // 'Fl_Shared_Image::compare()' - Compare two shared images...
76 Fl_Shared_Image::compare(Fl_Shared_Image
**i0
, // I - First image
77 Fl_Shared_Image
**i1
) { // I - Second image
78 int i
= strcmp((*i0
)->name(), (*i1
)->name());
81 else if (((*i0
)->w() == 0 && (*i1
)->original_
) ||
82 ((*i1
)->w() == 0 && (*i0
)->original_
)) return 0;
83 else if ((*i0
)->w() != (*i1
)->w()) return (*i0
)->w() - (*i1
)->w();
84 else return (*i0
)->h() - (*i1
)->h();
89 Creates an empty shared image.
90 The constructors create a new shared image record in the image cache.
92 <P>The constructors are protected and cannot be used directly
93 from a program. Use the get() method instead.
95 Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) {
105 Creates a shared image from its filename and its corresponding Fl_Image* img.
106 The constructors create a new shared image record in the image cache.
108 <P>The constructors are protected and cannot be used directly
109 from a program. Use the get() method instead.
111 Fl_Shared_Image::Fl_Shared_Image(const char *n
, // I - Filename
112 Fl_Image
*img
) // I - Image
114 name_
= new char[strlen(n
) + 1];
115 strcpy((char *)name_
, n
);
128 // 'Fl_Shared_Image::add()' - Add a shared image to the array.
132 Fl_Shared_Image::add() {
133 Fl_Shared_Image
**temp
; // New image pointer array...
135 if (num_images_
>= alloc_images_
) {
136 // Allocate more memory...
137 temp
= new Fl_Shared_Image
*[alloc_images_
+ 32];
140 memcpy(temp
, images_
, alloc_images_
* sizeof(Fl_Shared_Image
*));
149 images_
[num_images_
] = this;
152 if (num_images_
> 1) {
153 qsort(images_
, num_images_
, sizeof(Fl_Shared_Image
*),
154 (compare_func_t
)compare
);
160 // 'Fl_Shared_Image::update()' - Update the dimensions of the shared images.
164 Fl_Shared_Image::update() {
169 data(image_
->data(), image_
->count());
174 The destructor free all memory and server resources that are
175 used by the image. The destructor is protected and cannot be
176 used directly from a program. Use the Fl_Shared_Image::release() method
179 Fl_Shared_Image::~Fl_Shared_Image() {
180 if (name_
) delete[] (char *)name_
;
181 if (alloc_image_
) delete image_
;
187 Releases and possibly destroys (if refcount <=0) a shared image.
188 In the latter case, it will reorganize the shared image array so that no hole will occur.
190 void Fl_Shared_Image::release() {
191 int i
; // Looping var...
194 if (refcount_
> 0) return;
196 for (i
= 0; i
< num_images_
; i
++)
197 if (images_
[i
] == this) {
200 if (i
< num_images_
) {
201 memmove(images_
+ i
, images_
+ i
+ 1,
202 (num_images_
- i
) * sizeof(Fl_Shared_Image
*));
210 if (num_images_
== 0 && images_
) {
220 /** Reloads the shared image from disk */
221 void Fl_Shared_Image::reload() {
222 // Load image from disk...
223 int i
; // Looping var
224 FILE *fp
; // File pointer
225 uchar header
[64]; // Buffer for auto-detecting files
226 Fl_Image
*img
; // New image
230 if ((fp
= fl_fopen(name_
, "rb")) != NULL
) {
231 if (fread(header
, 1, sizeof(header
), fp
)==0) { /* ignore */ }
237 // Load the image as appropriate...
238 if (memcmp(header
, "#define", 7) == 0) // XBM file
239 img
= new Fl_XBM_Image(name_
);
240 else if (memcmp(header
, "/* XPM */", 9) == 0) // XPM file
241 img
= new Fl_XPM_Image(name_
);
243 // Not a standard format; try an image handler...
244 for (i
= 0, img
= 0; i
< num_handlers_
; i
++) {
245 img
= (handlers_
[i
])(name_
, header
, sizeof(header
));
252 if (alloc_image_
) delete image_
;
256 if ((img
->w() != w() && w()) || (img
->h() != h() && h())) {
257 // Make sure the reloaded image is the same size as the existing one.
258 Fl_Image
*temp
= img
->copy(w(), h());
271 // 'Fl_Shared_Image::copy()' - Copy and resize a shared image...
275 Fl_Shared_Image::copy(int W
, int H
) {
276 Fl_Image
*temp_image
; // New image file
277 Fl_Shared_Image
*temp_shared
; // New shared image
279 // Make a copy of the image we're sharing...
280 if (!image_
) temp_image
= 0;
281 else temp_image
= image_
->copy(W
, H
);
283 // Then make a new shared image...
284 temp_shared
= new Fl_Shared_Image();
286 temp_shared
->name_
= new char[strlen(name_
) + 1];
287 strcpy((char *)temp_shared
->name_
, name_
);
289 temp_shared
->refcount_
= 1;
290 temp_shared
->image_
= temp_image
;
291 temp_shared
->alloc_image_
= 1;
293 temp_shared
->update();
300 // 'Fl_Shared_Image::color_average()' - Blend colors...
304 Fl_Shared_Image::color_average(Fl_Color c
, // I - Color to blend with
305 float i
) { // I - Blend fraction
308 image_
->color_average(c
, i
);
314 // 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale...
318 Fl_Shared_Image::desaturate() {
321 image_
->desaturate();
327 // 'Fl_Shared_Image::draw()' - Draw a shared image...
331 Fl_Shared_Image::draw(int X
, int Y
, int W
, int H
, int cx
, int cy
) {
332 if (image_
) image_
->draw(X
, Y
, W
, H
, cx
, cy
);
333 else Fl_Image::draw(X
, Y
, W
, H
, cx
, cy
);
338 // 'Fl_Shared_Image::uncache()' - Uncache the shared image...
341 void Fl_Shared_Image::uncache()
343 if (image_
) image_
->uncache();
348 /** Finds a shared image from its named and size specifications */
349 Fl_Shared_Image
* Fl_Shared_Image::find(const char *n
, int W
, int H
) {
350 Fl_Shared_Image
*key
, // Image key
351 **match
; // Matching image
354 key
= new Fl_Shared_Image();
355 key
->name_
= new char[strlen(n
) + 1];
356 strcpy((char *)key
->name_
, n
);
360 match
= (Fl_Shared_Image
**)bsearch(&key
, images_
, num_images_
,
361 sizeof(Fl_Shared_Image
*),
362 (compare_func_t
)compare
);
367 (*match
)->refcount_
++;
377 \brief Find or load an image that can be shared by multiple widgets.
379 Gets a shared image, if it exists already ; it will return it.
380 If it does not exist or if it exist but with other size,
381 then the existing image is deleted and replaced
382 by a new image from the n filename of the proper dimension.
383 If n is not a valid image filename, then get() will return NULL.
385 Shared JPEG and PNG images can also be created from memory by using their
386 named memory access constructor.
388 \param n name of the image
389 \param W, H desired size
391 \see Fl_Shared_Image::find(const char *n, int W, int H)
392 \see Fl_Shared_Image::release()
393 \see Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data)
394 \see Fl_PNG_Image::Fl_PNG_Image (const char *name_png, const unsigned char *buffer, int maxsize)
396 Fl_Shared_Image
* Fl_Shared_Image::get(const char *n
, int W
, int H
) {
397 Fl_Shared_Image
*temp
; // Image
399 if ((temp
= find(n
, W
, H
)) != NULL
) return temp
;
401 if ((temp
= find(n
)) == NULL
) {
402 temp
= new Fl_Shared_Image(n
);
412 if ((temp
->w() != W
|| temp
->h() != H
) && W
&& H
) {
413 temp
= (Fl_Shared_Image
*)temp
->copy(W
, H
);
422 /** Adds a shared image handler, which is basically a test function for adding new formats */
423 void Fl_Shared_Image::add_handler(Fl_Shared_Handler f
) {
424 int i
; // Looping var...
425 Fl_Shared_Handler
*temp
; // New image handler array...
427 // First see if we have already added the handler...
428 for (i
= 0; i
< num_handlers_
; i
++) {
429 if (handlers_
[i
] == f
) return;
432 if (num_handlers_
>= alloc_handlers_
) {
433 // Allocate more memory...
434 temp
= new Fl_Shared_Handler
[alloc_handlers_
+ 32];
436 if (alloc_handlers_
) {
437 memcpy(temp
, handlers_
, alloc_handlers_
* sizeof(Fl_Shared_Handler
));
443 alloc_handlers_
+= 32;
446 handlers_
[num_handlers_
] = f
;
452 /** Removes a shared image handler */
453 void Fl_Shared_Image::remove_handler(Fl_Shared_Handler f
) {
454 int i
; // Looping var...
456 // First see if the handler has been added...
457 for (i
= 0; i
< num_handlers_
; i
++) {
458 if (handlers_
[i
] == f
) break;
461 if (i
>= num_handlers_
) return;
463 // OK, remove the handler from the array...
466 if (i
< num_handlers_
) {
467 // Shift later handlers down 1...
468 memmove(handlers_
+ i
, handlers_
+ i
+ 1,
469 (num_handlers_
- i
) * sizeof(Fl_Shared_Handler
));
475 // End of "$Id: Fl_Shared_Image.cxx 8306 2011-01-24 17:04:22Z matt $".