Animated GIF support (Fl_Anim_GIF_Image class) (#375)

This commit is contained in:
wcout
2023-01-21 17:27:58 +01:00
committed by GitHub
parent 1fc269b0d4
commit 2ddfd9d949
32 changed files with 3082 additions and 472 deletions
+185
View File
@@ -0,0 +1,185 @@
//
// Fl_Anim_GIF_Image class header for the Fast Light Tool Kit (FLTK).
//
// Copyright 2016-2022 by Christian Grabner <wcout@gmx.net>.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#ifndef Fl_Anim_Gif_Image_H
#define Fl_Anim_Gif_Image_H
// forward declarations
class Fl_Image;
class Fl_Widget;
#include <FL/Fl_GIF_Image.H>
// Load and display animater GIF images
class FL_EXPORT Fl_Anim_GIF_Image : public Fl_GIF_Image {
class FrameInfo; // internal helper class
public:
/**
When opening an Fl_Anim_GIF_Image there are some options
that can be passed in a `flags` value.
*/
enum Flags {
/**
This flag indicates to the loader that it should not start
the animation immediately after successful load, which is
the default.
It can be started later using the \ref start() method.
*/
DONT_START = 1,
/**
This flag indicates to the loader that it should not
resize the canvas widget of the animation to the dimensions
of the animation, which is the default.
Needed for special use cases.
*/
DONT_RESIZE_CANVAS = 2,
/**
This flag indicates to the loader that it should not
set the animation as \ref image() member of the canvas widget,
which is the default.
Needed for special use cases.
*/
DONT_SET_AS_IMAGE = 4,
/**
Often frames change just a small area of the animation canvas.
This flag indicates to the loader to try using less memory
by storing frame data not as canvas-sized images but use the
sizes defined in the GIF file.
The drawbacks are higher cpu usage during playback and maybe
minor artefacts when resized.
*/
OPTIMIZE_MEMORY = 8,
/**
This flag can be used to print informations about the
decoding process to the console.
*/
LOG_FLAG = 64,
/**
This flag can be used to print even more informations about
the decoding process to the console.
*/
DEBUG_FLAG = 128
};
// -- constructors and destructor
Fl_Anim_GIF_Image(const char *filename, Fl_Widget *canvas = 0, unsigned short flags = 0);
Fl_Anim_GIF_Image(const char* imagename, const unsigned char *data,
const size_t length, Fl_Widget *canvas = 0,
unsigned short flags = 0);
Fl_Anim_GIF_Image();
~Fl_Anim_GIF_Image() FL_OVERRIDE;
// -- file handling
bool load(const char *name, const unsigned char *imgdata=NULL, size_t imglength=0);
bool valid() const;
// -- getters and setters
void frame_uncache(bool uncache);
bool frame_uncache() const;
double delay(int frame_) const;
void delay(int frame, double delay);
void canvas(Fl_Widget *canvas, unsigned short flags = 0);
Fl_Widget *canvas() const;
int canvas_w() const;
int canvas_h() const;
bool is_animated() const;
const char *name() const;
void speed(double speed);
double speed() const;
// -- animation
int frames() const;
void frame(int frame);
int frame() const;
Fl_Image *image() const;
Fl_Image *image(int frame) const;
bool start();
bool stop();
bool next();
/** Return if the animation is currently running or stopped.
\return true if the animation is running
*/
bool playing() const { return valid() && Fl::has_timeout(cb_animate, (void *)this); }
// -- image data
Fl_Anim_GIF_Image& resize(int w, int h);
Fl_Anim_GIF_Image& resize(double scale);
int frame_x(int frame) const;
int frame_y(int frame) const;
int frame_w(int frame) const;
int frame_h(int frame) const;
// -- overriden methods
void color_average(Fl_Color c, float i) FL_OVERRIDE;
Fl_Image *copy(int W, int H) const FL_OVERRIDE;
Fl_Image *copy() const { return Fl_Pixmap::copy(); }
void desaturate() FL_OVERRIDE;
void draw(int x, int y, int w, int h, int cx = 0, int cy = 0) FL_OVERRIDE;
void uncache() FL_OVERRIDE;
// -- debugging and logging
int debug() const;
// -- static methods
static int frame_count(const char *name, const unsigned char *imgdata = NULL, size_t imglength = 0);
/**
The loop flag can be used to (dis-)allow loop count.
If set (which is the default), the animation will be
stopped after the number of repeats specified in the
GIF file (typically this count is set to 'forever' anyway).
If cleared the animation will always be 'forever',
regardless of what is specified in the GIF file.
*/
static bool loop;
/**
The min_delay value can be used to set a minimum value
for the frame delay for playback. This is to prevent
CPU hogs caused by images with very low delay rates.
This is a global value for all Fl_Anim_GIF_Image objects.
*/
static double min_delay;
protected:
bool next_frame();
void clear_frames();
void set_frame(int frame);
static void cb_animate(void *d);
void scale_frame();
void set_frame();
void on_frame_data(Fl_GIF_Image::GIF_FRAME &f) FL_OVERRIDE;
void on_extension_data(Fl_GIF_Image::GIF_FRAME &f) FL_OVERRIDE;
private:
char *name_;
unsigned short flags_;
Fl_Widget *canvas_;
bool uncache_;
bool valid_;
int frame_; // current frame
double speed_;
FrameInfo *fi_;
};
#endif // Fl_Anim_Gif_Image_H
+43 -2
View File
@@ -1,7 +1,7 @@
//
// GIF image header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -36,10 +36,51 @@ public:
// constructor with length (since 1.4.0)
Fl_GIF_Image(const char* imagename, const unsigned char *data, const size_t length);
static bool is_animated(const char *name_);
/** Sets how the shared image core routine should treat animated GIF files.
The default is to treat them as ordinary GIF's e.g. it creates a Fl_GIF_Image object.
If this variable is set, then an animated GIF object Fl_Anim_GIF_Image is created.
*/
static bool animate;
protected:
void load_gif_(class Fl_Image_Reader &rdr);
// Proteced constructors needed for animated GIF support through Fl_Anim_GIF_Image.
Fl_GIF_Image(const char* filename, bool anim);
Fl_GIF_Image(const char* imagename, const unsigned char *data, const size_t length, bool anim);
// Protected default constructor needed for Fl_Anim_GIF_Image.
Fl_GIF_Image();
void load_gif_(class Fl_Image_Reader &rdr, bool anim=false);
void load(const char* filename, bool anim);
void load(const char* imagename, const unsigned char *data, const size_t length, bool anim);
// Internal structure to "glue" animated GIF support into Fl_GIF_Image.
// This data is passed during decoding to the Fl_Anim_GIF_Image class.
struct GIF_FRAME {
int ifrm, width, height, x, y, w, h,
clrs, bkgd, trans,
dispose, delay;
const uchar *bptr;
const struct CPAL {
uchar r, g, b;
} *cpal;
GIF_FRAME(int frame, uchar *data) : ifrm(frame), bptr(data) {}
GIF_FRAME(int frame, int W, int H, int fx, int fy, int fw, int fh, uchar *data) :
ifrm(frame), width(W), height(H), x(fx), y(fy), w(fw), h(fh), bptr(data) {}
void disposal(int mode, int delay) { dispose = mode; this->delay = delay; }
void colors(int nclrs, int bg, int tp) { clrs = nclrs; bkgd = bg; trans = tp; }
};
// Internal virtual methods, which are called during decoding to pass data
// to the Fl_Anim_GIF_Image class.
virtual void on_frame_data(GIF_FRAME &gf) {}
virtual void on_extension_data(GIF_FRAME &gf) {}
private:
void lzw_decode(Fl_Image_Reader &rdr, uchar *Image, int Width, int Height, int CodeSize, int ColorMapSize, int Interlace);
};
#endif
+3
View File
@@ -272,6 +272,9 @@ public:
An internal copy is made of the original image before
changes are applied, to avoid modifying the original image.
\note The RGB color of \ref FL_BACKGROUND_COLOR may change when the
connection to the display is made. See fl_open_display().
*/
void inactive() { color_average(FL_GRAY, .33f); }
virtual void desaturate();
+4
View File
@@ -81,6 +81,10 @@ set (FLUID_SOURCES
############################################################
set (IMAGE_SOURCES
animgifimage
animgifimage-play
animgifimage-resize
animgifimage-simple
howto-simple-svg
)
+5 -1
View File
@@ -22,7 +22,11 @@ SHELL = /bin/sh
.SILENT:
# Executables
ALL = browser-simple$(EXEEXT) \
ALL = animgifimage$(EXEEXT) \
animgifimage-play$(EXEEXT) \
animgifimage-simple$(EXEEXT) \
animgifimage-resize$(EXEEXT) \
browser-simple$(EXEEXT) \
cairo-draw-x$(EXEEXT) \
chart-simple$(EXEEXT) \
draggable-group$(EXEEXT) \
+237
View File
@@ -0,0 +1,237 @@
//
// Demonstrates how to play an animated GIF file
// under application control frame by frame if
// this is needed.
// Also demonstrates how to use a single animation
// object to load multiple animations.
//
// animgifimage <file> [-r] [-s speed_factor]
//
// Multiple files can be specified e.g. testsuite/*
//
// Use keys '+'/'-'/Enter to change speed, ' ' to pause.
// Right key changes to next frame in paused mode.
// 'n' changes to next file, 'r' toggles reverse play.
//
#include <FL/Fl_Anim_GIF_Image.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl.H>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static double speed_factor = 1.; // slow down/speed up playback by factor
static bool reverse = false; // true = play animation backwards
static bool paused = false; // flag for paused animation
static bool frame_info = false; // flag to update current frame info in title
static Fl_Anim_GIF_Image animgif; // the animation object
static char **Argv = 0; // copy of main() argv[]
static int Argc = 0; // copy of main() argc
static int current_arg = 0; // current index in argv[]
static int next_arg() {
while (1) {
current_arg++;
if (current_arg >= Argc) {
current_arg = 1;
}
if (Argv[current_arg]) break;
}
return current_arg;
}
static const char *next_file() {
while (Argv[next_arg()][0] == '-') ;
return Argv[current_arg];
}
static void set_title() {
char buf[200];
char fi[50];
if (frame_info)
snprintf(fi, sizeof(fi), "frame %d/%d", animgif.frame() + 1, animgif.frames());
else
snprintf(fi, sizeof(fi), "%d frames", animgif.frames());
snprintf(buf, sizeof(buf), "%s (%s) x %3.2f %s%s",
Argv[current_arg], fi,
speed_factor, reverse ? "reverse" : "",
paused ? " PAUSED" : "");
Fl::first_window()->copy_label(buf);
}
static void cb_anim(void *d_) {
Fl_Anim_GIF_Image *animgif = (Fl_Anim_GIF_Image *)d_;
int frame(animgif->frame());
// switch to next/previous frame
if (reverse) {
animgif->canvas()->window()->redraw();
frame--;
if (frame < 0) {
frame = animgif->frames() - 1;
}
}
else {
frame++;
if (frame >= animgif->frames()) {
frame = 0;
}
}
// set the frame (and update canvas)
animgif->frame(frame);
// setup timer for next frame
if (!paused && animgif->delay(frame)) {
Fl::repeat_timeout(animgif->delay(frame) / speed_factor, cb_anim, d_);
}
if (frame_info)
set_title();
}
static void next_frame() {
cb_anim(&animgif);
}
static void toggle_pause() {
paused = !paused;
set_title();
if (paused)
Fl::remove_timeout(cb_anim, &animgif);
else
next_frame();
set_title();
}
static void toggle_info() {
frame_info = !frame_info;
set_title();
}
static void toggle_reverse() {
reverse = !reverse;
set_title();
}
static void zoom(bool out) {
int W = animgif.w();
int H = animgif.h();
// Note: deliberately no range check (use key 'N' to reset)
static const double f = 1.05;
if (out)
animgif.resize((double)W/f, (double)H/f);
else
animgif.resize(f*W, f*H);
}
static void change_speed(int dir_) {
if (dir_> 0) {
speed_factor += (speed_factor < 1) ? 0.01 : 0.1;
if (speed_factor > 100)
speed_factor = 100.;
}
else if (dir_ < 0) {
speed_factor -= (speed_factor > 1) ? 0.1 : 0.01;
if (speed_factor < 0.01)
speed_factor = 0.01;
}
else {
speed_factor = 1.;
}
set_title();
}
static void load_next() {
Fl::remove_timeout(cb_anim, &animgif);
paused = false;
animgif.load(next_file());
animgif.canvas()->window()->redraw();
// check if loading succeeded
printf("valid: %d frames: %d\n", animgif.valid(), animgif.frames());
if (animgif.valid()) {
printf("play '%s'%s with %3.2f x speed\n", animgif.name(),
(reverse ? " reverse" : ""), speed_factor);
animgif.frame(reverse ? animgif.frames() - 1 : 0);
// setup first timeout, but check for zero-delay (normal GIF)!
if (animgif.delay(animgif.frame())) {
Fl::add_timeout(animgif.delay(animgif.frame()) / speed_factor, cb_anim, &animgif);
}
}
set_title();
}
static int events(int event_) {
if (event_ == FL_SHORTCUT && Fl::first_window()) {
switch (Fl::event_key()) {
case '+': change_speed(1); break;
case '-': change_speed(-1); break;
case FL_Enter: change_speed(0); break;
case 'n': load_next(); break;
case 'z': zoom(Fl::event_shift()); break;
case 'i': toggle_info(); break; // Note: this can raise cpu usage considerably!
case 'r': toggle_reverse(); break;
case ' ': toggle_pause(); break;
case FL_Right:
if (paused && Fl::get_key(FL_Right)) next_frame();
break;
default:
return 0;
}
Fl::first_window()->redraw();
return 1;
}
return 0;
}
int main(int argc, char *argv[]) {
// setup play parameters from args
Argv = argv;
Argc = argc;
int n = 0;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-r"))
reverse = !reverse;
else if (!strcmp(argv[i], "-s") && i + 1 < argc) {
i++;
speed_factor = atof(argv[i]);
argv[i] = 0;
}
else if (argv[i][0] != '-') {
n++;
continue;
}
else {
printf("Invalid argument: '%s'\n", argv[i]);
exit(1);
}
}
if (!n) {
fprintf(stderr, "Test program for application controlled GIF animation.\n");
fprintf(stderr, "Please specify one or more image files!\n");
exit(0);
}
if (speed_factor < 0.01 || speed_factor > 100)
speed_factor = 1.;
Fl_Double_Window win(800, 600);
// prepare a canvas for the animation
// (we want to show it in the center of the window)
Fl_Box canvas(0, 0, win.w(), win.h());
Fl_Box help(0, win.h()-20, win.w(), 20, "Keys: N=next file, I=toggle info, R=play reverse, +/-/Enter/Space=change speed, Z=Zoom");
win.resizable(win);
win.end();
win.show();
Fl::add_handler(events);
// use the 'DONT_RESIZE_CANVAS' flag to tell the animation
// not to change the canvas size (which is the default).
unsigned short flags = Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS;
// flags |= Fl_Anim_GIF_Image::DEBUG_FLAG|Fl_Anim_GIF_Image::LOG_FLAG;
animgif.canvas(&canvas, flags);
load_next();
return Fl::run();
}
+185
View File
@@ -0,0 +1,185 @@
//
// Test program for Fl_Anim_GIF_Image::copy().
//
#include <FL/Fl_Anim_GIF_Image.H>
#include <FL/Fl_Image.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <stdio.h>
#include <stdlib.h>
static Fl_Anim_GIF_Image *orig = 0;
static bool draw_grid = true;
static int events(int event_) {
if (event_ == FL_SHORTCUT && Fl::first_window()) {
if (Fl::event_key()=='g') {
draw_grid = !draw_grid;
printf("grid: %s\n", (draw_grid ? "ON" : "OFF"));
}
else if (Fl::event_key()=='b') {
if (Fl_Image::scaling_algorithm() != FL_RGB_SCALING_BILINEAR)
Fl_Image::scaling_algorithm(FL_RGB_SCALING_BILINEAR);
else
Fl_Image::scaling_algorithm(FL_RGB_SCALING_NEAREST);
printf("bilenear: %s\n", (Fl_Image::scaling_algorithm() != FL_RGB_SCALING_BILINEAR ? "OFF" : "ON"));
}
else
return 0;
Fl::first_window()->redraw();
}
return 1;
}
class Canvas : public Fl_Box {
typedef Fl_Box Inherited;
public:
Canvas(int x, int y, int w, int h) :
Inherited(x, y, w, h) {}
void draw() FL_OVERRIDE {
if (draw_grid) {
// draw a transparency grid as background
static const Fl_Color C1 = fl_rgb_color(0xcc, 0xcc, 0xcc);
static const Fl_Color C2 = fl_rgb_color(0x88, 0x88, 0x88);
static const int SZ = 8;
for (int y = 0; y < h(); y += SZ) {
for (int x = 0; x < w(); x += SZ) {
fl_color(x%(SZ * 2) ? y%(SZ * 2) ? C1 : C2 : y%(SZ * 2) ? C2 : C1);
fl_rectf(x, y, 32, 32);
}
}
}
// draw the current image frame over the grid
Inherited::draw();
}
void do_resize(int W, int H) {
if (image() && (image()->w() != W || image()->h() != H)) {
Fl_Anim_GIF_Image *animgif = (Fl_Anim_GIF_Image *)image();
animgif->stop();
image(0);
// delete already copied images
if (animgif != orig ) {
delete animgif;
}
Fl_Anim_GIF_Image *copied = (Fl_Anim_GIF_Image *)orig->copy(W, H);
if (!copied->valid()) { // check success of copy
Fl::warning("Fl_Anim_GIF_Image::copy() %d x %d failed", W, H);
}
else {
printf("resized to %d x %d\n", copied->w(), copied->h());
}
copied->canvas(this, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
}
window()->cursor(FL_CURSOR_DEFAULT);
}
static void do_resize_cb(void *d) {
Canvas *c = (Canvas *)d;
c->do_resize(c->w(), c->h());
}
void resize(int x, int y, int w, int h) FL_OVERRIDE {
Inherited::resize(x, y, w, h);
// decouple resize event from actual resize operation
// to avoid lockups..
Fl::remove_timeout(do_resize_cb, this);
Fl::add_timeout(0.1, do_resize_cb, this);
window()->cursor(FL_CURSOR_WAIT);
}
};
int main(int argc, char *argv[]) {
// setup play parameters from args
const char *fileName = 0;
bool bilinear = false;
bool optimize = false;
bool uncache = false;
bool debug = false;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-b")) // turn bilinear scaling on
bilinear = true;
else if (!strcmp(argv[i], "-o")) // turn optimize on
optimize = true;
else if (!strcmp(argv[i], "-g")) // disable grid
draw_grid = false;
else if (!strcmp(argv[i], "-u")) // uncache
uncache = true;
else if (!strcmp(argv[i], "-d")) // debug
debug = true;
else if (argv[i][0] != '-' && !fileName) {
fileName = argv[i];
}
else if (argv[i][0] == '-') {
printf("Invalid argument: '%s'\n", argv[i]);
exit(1);
}
}
if (!fileName) {
fprintf(stderr, "Test program for animated copy.\n");
fprintf(stderr, "Usage: %s fileName [-b]ilinear [-o]ptimize [-g]rid [-u]ncache\n", argv[0]);
exit(0);
}
Fl_Anim_GIF_Image::min_delay = 0.1; // set a minumum delay for playback
Fl_Double_Window win(640, 480);
// prepare a canvas for the animation
// (we want to show it in the center of the window)
Canvas canvas(0, 0, win.w(), win.h());
win.resizable(win);
win.size_range(1, 1);
win.end();
win.show();
// create/load the animated gif and start it immediately.
// We use the 'DONT_RESIZE_CANVAS' flag here to tell the
// animation not to change the canvas size (which is the default).
int flags = Fl_Anim_GIF_Image::Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS;
if (optimize) {
flags |= Fl_Anim_GIF_Image::OPTIMIZE_MEMORY;
printf("Using memory optimization (if image supports)\n");
}
if (debug) {
flags |= Fl_Anim_GIF_Image::DEBUG_FLAG;
}
orig = new Fl_Anim_GIF_Image(/*name_=*/ fileName,
/*canvas_=*/ &canvas,
/*flags_=*/ flags );
// check if loading succeeded
printf("%s: valid: %d frames: %d uncache: %d\n",
orig->name(), orig->valid(), orig->frames(), orig->frame_uncache());
if (orig->valid()) {
win.copy_label(fileName);
// print information about image optimization
int n = 0;
for (int i = 0; i < orig->frames(); i++) {
if (orig->frame_x(i) != 0 || orig->frame_y(i) != 0) n++;
}
printf("image has %d optimized frames\n", n);
Fl_Image::scaling_algorithm(FL_RGB_SCALING_NEAREST);
if (bilinear) {
Fl_Image::scaling_algorithm(FL_RGB_SCALING_BILINEAR);
printf("Using bilinear scaling - can be slow!\n");
// NOTE: this can be *really* slow with large sizes, if FLTK
// has to resize on its own without hardware scaling enabled.
}
orig->frame_uncache(uncache);
if (uncache) {
printf("Caching disabled - watch cpu load!\n");
}
// set initial size to fit into window
double ratio = orig->valid() ? (double)orig->w() / orig->h() : 1;
int W = win.w() - 40;
int H = (double)W / ratio;
printf("original size: %d x %d\n", orig->w(), orig->h());
win.size(W, H);
Fl::add_handler(events);
return Fl::run();
}
}
+40
View File
@@ -0,0 +1,40 @@
//
// Minimal program for displaying an animated GIF file
// with the Fl_Anim_GIF_Image class.
//
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Anim_GIF_Image.H>
#include <FL/Fl.H>
#include <stdio.h>
int main(int argc, char *argv[]) {
Fl_Double_Window win(400, 300, "Fl_Anim_GIF_Image demo");
// prepare a canvas (widget) for the animation
Fl_Box canvas(20, 40, win.w()-40, win.h()-80, "Hello from FLTK GIF-animation!");
canvas.align(FL_ALIGN_TOP|FL_ALIGN_IMAGE_BACKDROP);
canvas.labelsize(20);
win.resizable(win);
win.end();
win.show(1, argv);
// Create and load the animated gif as image
// of the `canvas` widget and start it immediately.
// We use the `DONT_RESIZE_CANVAS` flag here to tell the
// animation *not* to change the canvas size (which is the default).
const char *default_image = "../test/pixmaps/fltk_animated.gif";
Fl_Anim_GIF_Image animgif(/*name_=*/ argv[1] ? argv[1] : default_image,
/*canvas_=*/ &canvas,
/*flags_=*/ Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
// resize animation to canvas size
animgif.scale(canvas.w(), canvas.h(), /*can_expand*/1, /*proportional*/1);
// check if loading succeeded
printf("%s: ld=%d, valid=%d, frames=%d, size=%dx%d\n",
animgif.name(), animgif.ld(), animgif.valid(),
animgif.frames(), animgif.canvas_w(), animgif.canvas_h());
if (animgif.valid())
return Fl::run();
}
+303
View File
@@ -0,0 +1,303 @@
//
// Test program for displaying animated GIF files using the
// Fl_Anim_GIF_Image class.
//
#include <FL/Fl_Anim_GIF_Image.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Tiled_Image.H>
#include <stdlib.h>
static int g_good_count = 0, g_bad_count = 0, g_frame_count = 0;
static const Fl_Color BackGroundColor = FL_GRAY; // use e.g. FL_RED to see
// transparent parts better
static const double RedrawDelay = 1./20; // interval [sec] for forced redraw
static void quit_cb(Fl_Widget* w_, void*) {
exit(0);
}
static void set_title(Fl_Window *win, Fl_Anim_GIF_Image *animgif) {
char buf[200];
snprintf(buf, sizeof(buf), "%s (%d frames) %2.2fx", fl_filename_name(animgif->name()),
animgif->frames(), animgif->speed());
if (animgif->frame_uncache())
strcat(buf, " U");
win->copy_label(buf);
win->copy_tooltip(buf);
}
static void cb_forced_redraw(void *d) {
Fl_Window *win = Fl::first_window();
while (win) {
if (!win->menu_window())
win->redraw();
win = Fl::next_window(win);
}
if (Fl::first_window())
Fl::repeat_timeout(RedrawDelay, cb_forced_redraw);
}
Fl_Window *openFile(const char *name, char *flags, bool close = false) {
// determine test options from 'flags'
bool uncache = strchr(flags, 'u');
char *d = flags - 1;
int debug = 0;
while ((d = strchr(++d, 'd'))) debug++;
bool optimize_mem = strchr(flags, 'm');
bool desaturate = strchr(flags, 'D');
bool average = strchr(flags, 'A');
bool test_tiles = strchr(flags, 'T');
bool test_forced_redraw = strchr(flags, 'f');
char *r = strchr(flags, 'r');
bool resizable = r && !test_tiles;
double scale = 1.0;
if (r && resizable) scale = atof(r+1);
if (scale <= 0.1 || scale > 5)
scale = resizable ? 0.7 : 1.0;
// setup window
Fl::remove_timeout(cb_forced_redraw);
Fl_Double_Window *win = new Fl_Double_Window(300, 300);
win->color(BackGroundColor);
if (close)
win->callback(quit_cb);
printf("Loading '%s'%s%s ... ", name,
uncache ? " (uncached)" : "",
optimize_mem ? " (optimized)" : "");
// create a canvas for the animation
Fl_Box *canvas = test_tiles ? 0 : new Fl_Box(0, 0, 0, 0); // canvas will be resized by animation
Fl_Box *canvas2 = 0;
unsigned short gif_flags = debug ? Fl_Anim_GIF_Image::LOG_FLAG : 0;
if (debug > 1)
gif_flags |= Fl_Anim_GIF_Image::DEBUG_FLAG;
if (optimize_mem)
gif_flags |= Fl_Anim_GIF_Image::OPTIMIZE_MEMORY;
// create animation, specifying this canvas as display widget
Fl_Anim_GIF_Image *animgif = new Fl_Anim_GIF_Image(name, canvas, gif_flags);
bool good( animgif->ld() == 0 && animgif->valid() );
printf("%s: %d x %d (%d frames) %s\n",
animgif->name(), animgif->w(), animgif->h(), animgif->frames(), good ? "OK" : "ERROR");
// for the statistics (when run on testsuite):
g_good_count += good;
g_bad_count += !good;
g_frame_count += animgif->frames();
win->user_data(animgif); // store address of image (see note in main())
// exercise the optional tests on the animation
animgif->frame_uncache(uncache);
if (scale != 1.0) {
animgif->resize(scale);
printf("TEST: resized %s by %.2f to %d x %d\n", animgif->name(), scale, animgif->w(), animgif->h());
}
if (average) {
printf("TEST: color_average %s\n", animgif->name());
animgif->color_average(FL_GREEN, 0.5); // currently hardcoded
}
if (desaturate) {
printf("TEST: desaturate %s\n", animgif->name());
animgif->desaturate();
}
int W = animgif->w();
int H = animgif->h();
if (animgif->frames()) {
if (test_tiles) {
// demonstrate a way how to use the animation with Fl_Tiled_Image
printf("TEST: use %s as tiles\n", animgif->name());
W *= 2;
H *= 2;
Fl_Tiled_Image *tiled_image = new Fl_Tiled_Image(animgif);
Fl_Group *group = new Fl_Group(0, 0, win->w(), win->h());
group->image(tiled_image);
group->align(FL_ALIGN_INSIDE);
animgif->canvas(group, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS | Fl_Anim_GIF_Image::DONT_SET_AS_IMAGE );
win->resizable(group);
} else {
// demonstrate a way how to use same animation in another canvas simultaneously:
// as the current implementation allows only automatic redraw of one canvas..
if (test_forced_redraw) {
if (W < 400) {
printf("TEST: open %s in another animation with application redraw\n", animgif->name());
canvas2 = new Fl_Box(W, 0, animgif->w(), animgif->h()); // another canvas for animation
canvas2->image(animgif); // is set to same animation!
W *= 2;
Fl::add_timeout(RedrawDelay, cb_forced_redraw); // force periodic redraw
}
}
}
// make window resizable (must be done before show())
if (resizable && canvas && !test_tiles) {
win->resizable(win);
}
win->size(W, H); // change to actual size of canvas
// start the animation
win->end();
win->show();
win->wait_for_expose();
set_title(win, animgif);
if (resizable && !test_tiles) {
// need to reposition the widgets (have been moved by setting resizable())
if (canvas && canvas2) {
canvas->resize(0, 0, W/2, canvas->h());
canvas2->resize(W/2, 0, W/2, canvas2->h());
}
else if (canvas) {
canvas->resize(0, 0, animgif->canvas_w(), animgif->canvas_h());
}
}
win->init_sizes(); // IMPORTANT: otherwise weird things happen at Ctrl+/- scaling
} else {
delete win;
return 0;
}
if (debug >=3) {
// open each frame in a separate window
for (int i = 0; i < animgif->frames(); i++) {
char buf[200];
snprintf(buf, sizeof(buf), "Frame #%d", i + 1);
Fl_Double_Window *win = new Fl_Double_Window(animgif->w(), animgif->h());
win->copy_tooltip(buf);
win->copy_label(buf);
win->color(BackGroundColor);
int w = animgif->image(i)->w();
int h = animgif->image(i)->h();
// in 'optimize_mem' mode frames must be offsetted to canvas
int x = (w == animgif->w() && h == animgif->h()) ? 0 : animgif->frame_x(i);
int y = (w == animgif->w() && h == animgif->h()) ? 0 : animgif->frame_y(i);
Fl_Box *b = new Fl_Box(x, y, w, h);
// get the frame image
b->image(animgif->image(i));
win->end();
win->show();
}
}
return win;
}
#include <FL/filename.H>
bool openDirectory(const char *dir, char *flags) {
dirent **list;
int nbr_of_files = fl_filename_list(dir, &list, fl_alphasort);
if (nbr_of_files <= 0)
return false;
int cnt = 0;
for (int i = 0; i < nbr_of_files; i++) {
char buf[512];
const char *name = list[i]->d_name;
if (!strcmp(name, ".") || !strcmp(name, "..")) continue;
const char *p = strstr(name, ".gif");
if (!p) p = strstr(name, ".GIF");
if (!p) continue;
if (*(p+4)) continue; // is no extension!
snprintf(buf, sizeof(buf), "%s/%s", dir, name);
if (strstr(name, "debug")) // hack: when name contains 'debug' open single frames
strcat(flags, "d");
if (openFile(buf, flags, cnt == 0))
cnt++;
}
return cnt != 0;
}
static void change_speed(double delta) {
Fl_Widget *below = Fl::belowmouse();
if (below && below->image()) {
Fl_Anim_GIF_Image *animgif = 0;
// Q: is there a way to determine Fl_Tiled_Image without using dynamic cast?
Fl_Tiled_Image *tiled = dynamic_cast<Fl_Tiled_Image *>(below->image());
animgif = tiled ?
dynamic_cast<Fl_Anim_GIF_Image *>(tiled->image()) :
dynamic_cast<Fl_Anim_GIF_Image *>(below->image());
if (animgif && animgif->playing()) {
double speed = animgif->speed();
if (!delta) speed = 1.;
else speed += delta;
if (speed < 0.1) speed = 0.1;
if (speed > 10) speed = 10;
animgif->speed(speed);
set_title(below->window(), animgif);
}
}
}
static int events(int event) {
if (event == FL_SHORTCUT) {
if (Fl::event_key() == '+')
change_speed(0.1);
else if (Fl::event_key() == '-')
change_speed(-0.1);
else if (Fl::event_key() == '0')
change_speed(0);
else
return 0;
return 1;
}
return 0;
}
static const char testsuite[] = "testsuite";
int main(int argc, char *argv[]) {
fl_register_images();
Fl::add_handler(events);
char *openFlags = (char *)calloc(1024, 1);
if (argc > 1) {
// started with argumemts
if (strstr(argv[1], "-h")) {
printf("Usage:\n"
" -t [directory] [-{flags}] open all files in directory (default name: %s) [with options]\n"
" filename [-{flags}] open single file [with options] \n"
" No arguments open a fileselector\n"
" {flags} can be: d=debug mode, u=uncached, D=desaturated, A=color averaged, T=tiled\n"
" m=minimal update, r[scale factor]=resize by 'scale factor'\n"
" Use keys '+'/'-/0' to change speed of the active image (belowmouse).\n", testsuite);
exit(1);
}
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-')
strcat(openFlags, &argv[i][1]);
}
if (strchr(openFlags, 't')) { // open all GIF-files in a given directory
const char *dir = testsuite;
for (int i = 2; i < argc; i++)
if (argv[i][0] != '-')
dir = argv[i];
openDirectory(dir, openFlags);
printf("Summary: good=%d, bad=%d, frames=%d\n", g_good_count, g_bad_count, g_frame_count);
} else { // open given file(s)
for (int i = 1; i < argc; i++)
if (argv[i][0] != '-')
openFile(argv[i], openFlags, strchr(openFlags, 'd'));
}
} else {
// started without arguments: choose file
Fl_GIF_Image::animate = true; // create animated shared .GIF images (e.g. file chooser)
while (1) {
Fl::add_timeout(0.1, cb_forced_redraw); // animate images in chooser
const char *filename = fl_file_chooser("Select a GIF image file","*.{gif,GIF}", NULL);
Fl::remove_timeout(cb_forced_redraw);
if (!filename)
break;
Fl_Window *win = openFile(filename, openFlags);
Fl::run();
// delete last window (which is now just hidden) to test destructors
// NOTE: it is essential that *before* doing this also the
// animated image is destroyed, otherwise it will crash
// because it's canvas will be gone.
// In order to keep this demo simple, the adress of the
// Fl_Anim_GIF_Image has been stored in the window's user_data.
// In a real-life application you will probably store
// it somewhere in the window's or canvas' object and destroy
// the image in the window's or canvas' destructor.
if (win && win->user_data())
delete ((Fl_Anim_GIF_Image *)win->user_data());
delete win;
}
}
return Fl::run();
}
+37 -9
View File
@@ -30,6 +30,7 @@
#include <FL/fl_utf8.h> // fl_fopen()
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_SVG_Image.H>
#include <FL/Fl_Anim_GIF_Image.H>
#include "../src/flstring.h"
#include <stdio.h>
@@ -51,6 +52,7 @@ static int image_header_written = 0;
static int jpeg_header_written = 0;
static int png_header_written = 0;
static int gif_header_written = 0;
static int animated_gif_header_written = 0;
static int bmp_header_written = 0;
static int svg_header_written = 0;
@@ -134,8 +136,19 @@ void Fluid_Image::write_static(int compressed) {
if (!img) return;
const char *idata_name = unique_id(this, "idata", fl_filename_name(name()), 0);
function_name_ = unique_id(this, "image", fl_filename_name(name()), 0);
// TODO: GIF, ICO, BMP
if (compressed && strcmp(fl_filename_ext(name()), ".gif")==0) {
if (is_animated_gif_) {
// Write animated gif image data...
write_c("\n");
if (animated_gif_header_written != write_number) {
write_c("#include <FL/Fl_Anim_GIF_Image.H>\n");
animated_gif_header_written = write_number;
}
write_c("static const unsigned char %s[] =\n", idata_name);
size_t nData = write_static_binary("AnimGIF");
write_c(";\n");
write_initializer("Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".gif")==0) {
// Write gif image data...
write_c("\n");
if (gif_header_written != write_number) {
@@ -146,7 +159,7 @@ void Fluid_Image::write_static(int compressed) {
size_t nData = write_static_binary("GIF");
write_c(";\n");
write_initializer("Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (compressed && strcmp(fl_filename_ext(name()), ".bmp")==0) {
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".bmp")==0) {
// Write bmp image data...
write_c("\n");
if (bmp_header_written != write_number) {
@@ -198,7 +211,7 @@ void Fluid_Image::write_static(int compressed) {
write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h());
write_c(";\n");
write_initializer( "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h());
} else if (compressed && strcmp(fl_filename_ext(name()), ".jpg")==0) {
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".jpg")==0) {
// Write jpeg image data...
write_c("\n");
if (jpeg_header_written != write_number) {
@@ -209,7 +222,7 @@ void Fluid_Image::write_static(int compressed) {
size_t nData = write_static_binary("JPEG");
write_c(";\n");
write_initializer("Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (compressed && strcmp(fl_filename_ext(name()), ".png")==0) {
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".png")==0) {
// Write png image data...
write_c("\n");
if (png_header_written != write_number) {
@@ -220,7 +233,7 @@ void Fluid_Image::write_static(int compressed) {
size_t nData = write_static_binary("PNG");
write_c(";\n");
write_initializer("Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
} else if (strcmp(fl_filename_ext(name()), ".svg")==0 || strcmp(fl_filename_ext(name()), ".svgz")==0) {
} else if (fl_ascii_strcasecmp(fl_filename_ext(name()), ".svg")==0 || fl_ascii_strcasecmp(fl_filename_ext(name()), ".svgz")==0) {
bool gzipped = (strcmp(fl_filename_ext(name()), ".svgz") == 0);
// Write svg image data...
if (compressed) {
@@ -242,7 +255,7 @@ void Fluid_Image::write_static(int compressed) {
}
} else {
// if FLUID runs from the command line, make sure that the image is not
// only loade but also rasterized, so we can write the RGB image data
// only loaded but also rasterized, so we can write the RGB image data
Fl_RGB_Image* rgb_image = NULL;
Fl_SVG_Image* svg_image = NULL;
if (img->d()>0)
@@ -279,6 +292,8 @@ void Fluid_Image::write_initializer(const char *type_name, const char *format, .
va_list ap;
va_start(ap, format);
write_c("static Fl_Image *%s() {\n", function_name_);
if (is_animated_gif_)
write_c("%sFl_GIF_Image::animate = true;\n", indent(1));
write_c("%sstatic Fl_Image *image = NULL;\n", indent(1));
write_c("%sif (!image)\n", indent(1));
write_c("%simage = new %s(", indent(2), type_name);
@@ -292,7 +307,11 @@ void Fluid_Image::write_initializer(const char *type_name, const char *format, .
void Fluid_Image::write_code(int bind, const char *var, int inactive) {
/* Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item.
This code calls a function output before by Fluid_Image::write_initializer() */
if (img) write_c("%s%s->%s%s( %s() );\n", indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_);
if (img) {
write_c("%s%s->%s%s( %s() );\n", indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_);
if (is_animated_gif_)
write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", indent(), function_name_, var);
}
}
void Fluid_Image::write_inline(int inactive) {
@@ -355,11 +374,20 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
return ret;
}
Fluid_Image::Fluid_Image(const char *iname) {
Fluid_Image::Fluid_Image(const char *iname)
: is_animated_gif_(false)
{
name_ = fl_strdup(iname);
written = 0;
refcount = 0;
img = Fl_Shared_Image::get(iname);
if (img && iname) {
const char *ext = fl_filename_ext(iname);
if (fl_ascii_strcasecmp(ext, ".gif")==0) {
int fc = Fl_Anim_GIF_Image::frame_count(iname);
if (fc > 0) is_animated_gif_ = true;
}
}
function_name_ = NULL;
}
+1
View File
@@ -24,6 +24,7 @@
#include <FL/Fl_Shared_Image.H>
class Fluid_Image {
bool is_animated_gif_;
const char *name_;
int refcount;
Fl_Shared_Image *img;
+122 -229
View File
@@ -21,236 +21,127 @@ void show_help(const char *name);
Fl_Double_Window *about_panel=(Fl_Double_Window *)0;
#include <FL/Fl_Pixmap.H>
static const char *idata_fluid[] = {
"96 96 32 1",
" \tc None",
".\tc #000100",
"+\tc #031F3F",
"@\tc #00366C",
"#\tc #2E302D",
"$\tc #0058AC",
"%\tc #0060BF",
"&\tc #4E504D",
"*\tc #14659F",
"=\tc #006DDC",
"-\tc #2C7087",
";\tc #0080FF",
">\tc #407B74",
",\tc #0F85F9",
"\'\tc #268CCD",
")\tc #7C7E7B",
"!\tc #2D92EC",
"~\tc #4498A9",
"{\tc #2F94FE",
"]\tc #5BA18C",
"^\tc #6BA674",
"/\tc #7DAD62",
"(\tc #93BD53",
"_\tc #A4A6A2",
":\tc #6CB6FF",
"<\tc #ABCC3F",
"[\tc #C4DA2A",
"}\tc #CACCC9",
"|\tc #DCE913",
"1\tc #BBDEFF",
"2\tc #FDFE00",
"3\tc #FDFFFC",
" \
",
" \
",
" \
",
" ........... \
",
" ...................... \
",
" ........................ \
",
" ........#&#&#&#&##...... \
",
" ....)__}33333333333}_... \
",
" ...&33333333333333333... \
",
" ...#33311133333333333... \
",
" ...&33!,{,;:333333333... \
",
" ...&3:,{{{{,13333333}... \
",
" ...&3!{{!{{,13333333}... \
",
" ...&3:!{{!{;13333333}... \
",
" ...&3{{{{{{;133333333... \
",
" ...&31,{{{;,33333333}... \
",
" ...&331{{{:133333333}... \
",
" ...&3333333333333333_... \
",
" ...&3333333333333333}... \
",
" ...&3333333333333333_... \
",
" ...&3333333333333333}... \
",
" ...&3333333333333333_... \
",
" ...&3333333333333333}... \
",
" ...&3333333333333333_... \
",
" ...&3333333331!,,;:3}... \
",
" ...&333333333{{{{{;:_... \
",
" ...&333333331,{!{!{{}... \
",
" ...&333333331{{{{{{,_... \
",
" ...)333333331{{!{{{{_... \
",
" ...)333333333{{{!{;:_... \
",
" ...)3333333331{;;;:3_... \
",
" ...)3333333333331333_... \
",
" ...)3333333333333333_... \
",
" ...)3333333333333333_... \
",
" ..._3333333333333333_... \
",
" ..._3333333333333333_... \
",
" ..._3333333333333333_... \
",
" ..._3333333333333333}.... \
",
" ...._33333333333333333#... \
",
" ....&333333333333333333_.... \
",
" ....&33333333333333333333).... \
",
" ....333333333333333333333}&.... \
",
" ...._33333333333333333333333.... \
",
" ....&333333333331:11333333333_.... \
",
" ....#33333333333:,,,;:333333333&.... \
",
" ....}3333333333:,!{{{;1333333333&.... \
",
" ....}33333333333{{{!{{,!3333333333.... \
",
" ....)333333333333{{{{!{{{3333333333_.... \
",
" ....#3333333333333!{{{{{,:33333333333&.... \
",
" ...._33333333333331{{!{,;1333333333333#.... \
",
" ...._333333333333333:;,;,13333333333333_.... \
",
" ...._333333333333333333113333333333333333_.... \
",
" ....&33333333333333333333333333331::1333333&.... \
",
" ...._333333333333333333333333333{,{{;{133333#... \
",
" ...._3333333333333333333333333331,{!{{,:33333}.... \
",
" ....&3333333333133333333333333333:{{{{{{:333333).... \
",
" ...#333333331{,,;:333333333333333:{!{!{{:3333333&.... \
",
" ....}33333333,{{{{;:333333333333331,{!{{;:33333333#... \
",
" ...._333333331,!{!{{,333333333333333{,{{;{1333333333.... \
",
" ....&3333333331{{{{{{{3333333333333333::::33333333333)....\
",
" ....+!:::::::::{{{{!{{;::::::::::::::::::::::::::!:::::+...\
. ",
" ...+=;;;;;;;;;;;;{{{{;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=...\
. ",
" ....%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%..\
.. ",
" ....@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$.\
... ",
" ...+%;;;;;;!!!;;;;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;!=;;;+\
.... ",
" ....%;;;;;!([<|^~]^([%;;;;;;;;;;;;;;;;;,(<\'=;;;;;;;!^/<[|\'=;\
;=+... ",
" ....$;;;;;\'|2>]22<|22[%=;;;;;;;;;;;;;;;;^22[%=;;;;;;!][22|%=;;\
;$.... ",
" ....@;;;;;;[2[%^2|*[22(%=;;;;;;;;;;;;;;;,/22|$=;;;;;;;;<22<%=;;;\
;$.... ",
" ....+=;;;;;~22^$%]~$|22>%=;;;;;;;;;;;;;;;;\'||^%=;;;;;;;,[22^$=;;\
;;;+.... ",
" ....%;;;;;,[22-%===\'22|*==;;;;;;;;;;;;;;;;;;=%=;;;;;;;;\'22|*%=;\
;;;;=+... ",
" ....$;;;;;;!22|$%;,;^22<$=;;;;;;;;;;;;;;;;;;===;;;;;;;;;^22|$==;;;\
;;;%.... ",
" ....@;;;;;\'](22[^]=;;<22^$==!~]/~=;!]]~;;;;{\'~]==;;;;~<<]<22($=;;\
;;;;;;@.... ",
" ....@;;;;;;]<|22|[<%;!|22-%\'[2222*=;/22(%;~|222(=;;;!<2|^[222>$=;;;\
;;;;;;+.... ",
" ....=;;;;;;;,[22>$===~22|$==,[22[%=;[22]%=,!|22]%=;![2|*%]22|*==;;;;\
;;;;;%+... ",
" ....@;;;;;;;;!|22*$=;;/22($=;,[22/$=\'222*%=;!|22-%;;<22>%=]22[$%;;;;\
;;;;;;;=.... ",
" ....@;;;;;;;;;~22[*==;;[22>%=;\'22|-%,^22[$=;,~22[$%;]22<$%=(22/$=;;;;\
;;;;;;;;@.... ",
" ....+;;;;;;;;;;^22<$=;;!222*$=;]22[$==[22/$=;;(22/$=![22]$=;|22-%=;;;;;\
;;;;;;;;+... ",
" ....;;;;;;;;;;;<22^%=;;]22[$=;;(22/$=~222-%=;;[22>%=]22|$%;~22|$==;;;;;\
;;;;;;;;;.... ",
" ....%;;;;;;;;;;;|22-%=;;(22/$=;{|22-%=<22|$%;;\'22|*%;<22<$==(22<$=;=;;;\
;;;;;;;;;;$.... ",
" ....+;;;;;;;;;;;!222$==;,|22>%=;~22|$=]|22($=;;]22[$%,|22^%=!|22^$=;;;;;;\
;;;;;;;;;;@.... ",
" ....+=;;;;;;;;;;;~22[$%;;\'22|*-/;]22($*[<22^$^=;(22/$(-222>$=(222->~;;;;;\
;;;;;;;;;;;=+.... ",
" ...+;;;;;;;;;;;;;(22/$=;;]22|*<\'=(22/*[~[22>(]=;|22>//=|22/$^(|2|-[%=;;;;\
;;;;;;;;;;;;=.... ",
" ....$;;;;;;;;;;;;;<22>%=;;]222|>==(222|^=|22|<%=;|222<%=(222|<-222|-==;;;;;\
;;;;;;;;;;;;$.... ",
" ....@;;;;;;;;;;;;;!|2|$=;;;\'[2[>%=;\'|2[]%=/2|/$==;^2|(*%=!(2|($%<2[-%=;;;;\
;;;;;;;;;;;;;;;@.... ",
"....@;;;;;;;;;;;;;;\'22($%;;;;=%%==;;;=%%%==;=%%==;;;=%===;;==%%====%%=,;;;;;\
;;;;;;;;;;;;;;;+... ",
"...+=;;;;;;;;;;!\'=,]22-%=;;;;;;==;=;;;===;=;;===;;;;;===;;;;=;=,;;,=;=;;;;;;\
;;;;;;;;;;;;;;;=....",
"...+;;;;;;;;;;;[2^=<2<$==;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
;;;;;;;;;;;;;;;+...",
"...+;;;;;;;;;;;22(\'2|*%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
;;;;;;;;;;;;;;;;+...",
"...+;;;;;;;;;;;^|<[[-%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
;;;;;;;;;;;;;;;+...",
"...+;;;;;;;;;;;;*~*%===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
;;;;;;;;;;;;;;;@...",
"...+;;;;;;;;;;;;;====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
;;;;;;;;;;;;;;;+...",
"....$=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
;;;;;;;;;;;;;=$....",
" .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\
+++++++++++++..... ",
" ............................................................................\
................. ",
" ...........................................................................\
................. ",
" ........................................................................\
.............. "
};
#include <FL/Fl_Anim_GIF_Image.H>
static const unsigned char idata_fluid[] =
{71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80,
77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254,
0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91,
161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108,
182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69,
84,83,67,65,80,69,50,46,48,3,1,0,0,0,33,249,4,5,10,0,31,0,44,0,0,0,0,96,0,96,0,
0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223,
120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201,
91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147,
241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28,
93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143,
90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153,
142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64,
188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120,
25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231,
105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218,
161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193,
232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254,
81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121,
51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163,
237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109,
100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72,
177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78,
83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195,
61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107,
246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250,
234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208,
216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103,
106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191,
255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16,
70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195,
0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98,
192,160,20,7,214,215,16,15,46,54,136,65,3,12,36,160,0,2,20,76,128,0,144,61,122,
120,65,3,9,84,112,227,139,8,28,144,0,3,10,56,41,133,4,57,182,183,98,15,16,60,88,
129,2,11,20,48,193,2,11,8,73,38,3,17,60,217,33,2,103,166,9,33,6,19,48,64,166,2,
110,74,145,162,150,27,241,64,226,131,114,162,201,166,2,14,200,185,64,3,117,118,
120,193,1,115,66,160,166,131,9,144,153,64,161,98,92,104,15,139,139,82,64,38,2,
16,68,48,1,5,16,128,25,38,164,28,126,57,36,168,82,92,32,40,166,139,102,137,39,
76,25,202,40,232,3,105,74,32,65,5,115,58,32,43,141,18,144,42,5,173,11,0,10,42,
150,58,62,197,67,151,47,38,170,225,140,108,150,169,40,174,183,74,152,172,2,138,
46,58,133,164,42,254,68,225,96,5,19,52,112,38,2,19,220,216,232,2,168,74,128,65,
145,7,80,192,32,156,155,58,152,65,5,69,54,43,5,5,9,36,48,193,183,13,44,27,225,
48,42,10,11,192,158,14,206,235,169,2,65,106,136,129,167,176,86,32,40,153,182,
90,128,232,160,26,82,224,233,160,79,98,208,232,144,7,23,96,111,132,170,202,224,
131,180,22,152,74,166,197,178,74,96,105,175,209,122,188,0,154,12,10,58,65,154,
23,12,76,230,202,231,202,233,235,152,189,218,202,177,20,17,100,105,144,158,18,
186,188,128,3,246,46,92,47,131,38,31,160,40,175,63,187,233,51,172,82,124,91,64,
154,52,51,144,233,134,22,246,101,109,132,35,51,96,179,20,130,62,205,32,175,10,
192,122,65,178,82,19,157,245,212,52,39,144,169,4,218,46,96,244,205,14,226,187,
234,125,20,38,171,246,141,24,144,249,243,178,81,71,43,232,219,82,180,253,54,6,
42,47,75,176,174,16,234,204,42,15,27,126,139,64,157,125,223,40,184,162,35,47,0,
235,141,93,67,109,172,5,35,67,235,238,134,254,146,250,144,100,132,135,75,78,38,
224,25,148,254,45,180,46,130,237,128,134,223,222,205,182,163,203,194,237,224,
157,62,177,184,97,222,100,70,219,177,167,94,115,158,168,4,19,120,58,180,20,125,
71,112,129,167,143,139,203,252,197,29,202,109,20,15,11,110,120,118,235,181,62,
112,128,5,52,215,27,168,227,16,32,192,224,228,13,60,160,55,200,109,91,94,0,5,38,
2,59,142,238,28,78,126,35,205,128,54,57,187,219,129,82,208,117,3,221,90,0,252,
1,7,144,128,167,140,118,36,48,133,13,101,237,59,141,15,136,213,184,143,65,78,
111,10,40,128,172,210,55,36,1,206,233,81,12,122,24,6,41,152,0,243,205,233,1,159,
235,16,238,234,48,162,14,185,204,115,13,50,216,201,130,247,165,147,193,12,81,10,
120,27,131,254,212,128,215,137,75,91,10,168,87,4,26,197,128,203,209,104,18,82,
185,218,134,120,165,67,7,229,42,86,13,58,34,18,143,232,174,92,133,236,74,76,12,
89,4,88,246,67,11,232,140,82,20,194,128,147,46,64,51,31,62,232,86,79,122,148,
226,141,158,104,196,207,49,72,2,51,234,216,25,171,104,129,170,253,32,0,27,146,
147,248,26,37,59,54,218,241,142,86,36,2,28,41,68,166,6,208,202,87,182,195,163,
32,39,164,42,234,109,8,1,10,152,82,15,17,55,200,70,74,168,144,10,226,144,3,40,
96,195,16,58,242,146,247,210,99,135,66,22,72,76,98,18,146,0,128,158,39,71,121,
34,9,224,238,141,1,72,165,42,87,201,202,86,186,242,149,176,140,165,44,103,201,
202,31,144,176,9,184,204,165,46,119,201,203,94,246,82,36,190,12,166,48,135,73,
76,34,76,175,152,200,76,102,49,75,16,2,0,33,249,4,5,10,0,31,0,44,30,0,4,0,38,0,
57,0,0,5,254,224,39,142,31,96,158,104,170,2,100,235,174,112,236,206,174,103,
223,56,158,210,60,205,113,185,91,111,152,201,136,56,25,100,50,232,25,246,126,71,
227,143,233,57,57,121,72,13,105,169,51,93,105,154,204,141,243,225,222,172,95,
151,70,227,209,126,128,65,116,186,85,92,127,168,115,44,156,218,204,147,236,111,
100,83,113,94,126,128,69,101,98,132,44,115,124,124,114,126,45,123,57,145,88,102,
56,149,60,110,153,156,157,158,159,160,161,162,149,142,120,145,165,76,164,168,
148,167,171,152,173,174,54,170,177,125,126,180,178,176,177,179,76,28,107,26,100,
163,34,97,69,69,192,162,74,196,197,163,201,201,155,160,204,196,206,159,208,117,
163,195,204,198,160,200,209,66,161,189,35,147,184,78,183,169,227,228,229,78,189,
191,231,226,62,208,225,186,154,208,108,231,150,212,240,174,238,247,236,181,36,
219,201,217,60,253,35,22,80,224,187,96,111,0,130,226,199,176,161,67,90,219,128,
61,196,49,144,204,68,27,3,139,93,244,144,49,137,175,143,32,67,138,244,149,225,
130,201,147,38,3,51,132,0,0,33,249,4,5,10,0,31,0,44,34,0,7,0,34,0,54,0,0,5,202,
224,39,138,94,105,158,168,57,174,236,154,190,104,43,143,112,237,205,179,13,227,
178,254,242,45,95,10,200,18,198,136,52,163,10,73,82,150,152,77,39,116,74,141,42,
167,206,39,52,123,171,122,191,224,176,120,76,46,155,207,232,244,151,195,230,156,
57,154,140,60,227,94,107,52,245,185,190,62,229,232,229,113,127,114,85,129,130,
134,83,1,126,130,23,134,25,136,138,127,140,135,80,137,141,134,124,76,144,127,
112,43,28,90,80,154,114,158,30,109,163,93,125,123,58,72,92,75,64,172,39,106,177,
76,175,63,69,175,112,119,152,46,172,133,162,61,92,161,190,182,89,141,26,65,92,
197,199,196,134,198,195,78,189,115,186,31,172,193,205,100,112,209,68,144,120,
102,208,116,180,90,193,25,26,224,93,222,114,229,34,231,25,233,31,25,23,240,241,
240,119,244,245,246,247,244,33,0,33,249,4,5,10,0,31,0,44,36,0,13,0,26,0,48,0,0,
5,196,224,39,138,156,102,114,99,170,174,100,230,186,26,43,143,220,107,163,243,
26,104,182,157,235,188,158,235,167,218,9,135,196,84,77,24,75,166,130,55,167,
106,153,209,224,164,88,44,103,123,205,150,162,217,207,177,155,164,246,178,208,
51,54,237,211,30,51,225,177,103,78,247,252,190,175,79,189,46,219,115,57,123,
124,44,129,132,123,125,133,136,42,0,139,136,137,41,139,0,141,30,93,100,31,144,
141,102,46,28,1,131,133,98,71,14,157,132,153,47,26,156,41,152,111,149,57,164,
154,104,76,97,164,171,101,39,78,84,86,97,31,108,25,128,146,83,71,26,146,118,79,
111,194,42,187,46,198,196,71,202,52,114,190,191,54,193,205,74,38,86,194,216,217,
218,219,136,102,171,194,178,43,146,173,188,42,227,170,199,214,234,214,25,23,238,
239,238,112,41,33,0,33,249,4,5,10,0,31,0,44,38,0,5,0,21,0,56,0,0,5,232,224,39,
142,80,52,158,104,202,101,25,151,190,98,166,105,172,11,167,44,171,125,156,125,
139,171,26,173,245,27,245,56,195,93,17,185,11,250,96,131,97,203,89,20,205,106,
181,170,199,99,67,102,127,219,174,231,11,3,132,129,231,159,57,204,217,186,223,
111,145,185,7,175,199,81,109,207,76,249,91,105,182,82,79,48,109,121,71,85,64,68,
135,39,52,127,112,76,26,130,136,132,133,57,58,47,121,34,92,149,57,28,1,153,118,
122,155,57,3,159,118,82,155,164,31,160,161,162,25,169,171,65,155,26,175,171,167,
53,158,170,171,154,58,79,186,160,138,192,193,194,39,190,118,55,73,160,0,0,120,
162,121,111,2,56,173,117,27,203,70,173,45,117,204,173,206,110,218,205,198,39,
215,191,39,177,156,197,110,73,96,231,235,117,71,189,190,167,124,240,162,74,186,
229,149,46,246,215,249,176,251,185,160,247,56,85,177,37,67,81,188,17,231,220,17,
99,199,176,225,186,61,16,35,74,220,19,2,0,59};
static Fl_Image *image_fluid() {
static Fl_Image *image = new Fl_Pixmap(idata_fluid);
Fl_GIF_Image::animate = true;
static Fl_Image *image = NULL;
if (!image)
image = new Fl_Anim_GIF_Image("fluid.animated.gif", idata_fluid, 2545);
return image;
}
@@ -275,6 +166,8 @@ Fl_Double_Window* make_about_panel() {
about_panel->hotspot(about_panel);
{ Fl_Box* o = new Fl_Box(10, 10, 115, 120);
o->image( image_fluid() );
((Fl_Anim_GIF_Image*)(image_fluid()))->canvas(o, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
((Fl_Anim_GIF_Image*)(o->image()))->speed(0.5f);
} // Fl_Box* o
{ Fl_Box* o = new Fl_Box(135, 10, 205, 75, "FLTK User\nInterface Designer\nVersion x.x.x");
o->color((Fl_Color)12);
+6 -5
View File
@@ -36,11 +36,12 @@ if (!cbuf[0]) {
}} {}
Fl_Window about_panel {
label {About FLUID} open
xywh {449 217 345 180} type Double color 50 selection_color 47 hide hotspot
code0 {\#include "../src/flstring.h"} non_modal
xywh {449 217 345 180} type Double color 50 selection_color 47 hotspot
code0 {\#include "../src/flstring.h"} non_modal visible
} {
Fl_Box {} {
image {icons/fluid-96.xpm} xywh {10 10 115 120}
Fl_Box {} {selected
image {icons/fluid.animated.gif} compress_image 1 xywh {10 10 115 120}
code0 {((Fl_Anim_GIF_Image*)(o->image()))->speed(0.5f);}
}
Fl_Box {} {
label {FLTK User
@@ -59,7 +60,7 @@ Version x.x.x}
}
Fl_Button {} {
label {View License...}
callback {show_help("license.html");} selected
callback {show_help("license.html");}
xywh {115 145 123 25} labelcolor 136
}
Fl_Return_Button {} {
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

+1
View File
@@ -471,6 +471,7 @@ set (IMGCPPFILES
Fl_BMP_Image.cxx
Fl_File_Icon2.cxx
Fl_GIF_Image.cxx
Fl_Anim_GIF_Image.cxx
Fl_Help_Dialog.cxx
Fl_ICO_Image.cxx
Fl_JPEG_Image.cxx
File diff suppressed because it is too large Load Diff
+418 -208
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -230,6 +230,7 @@ IMGCPPFILES = \
Fl_BMP_Image.cxx \
Fl_File_Icon2.cxx \
Fl_GIF_Image.cxx \
Fl_Anim_GIF_Image.cxx \
Fl_Help_Dialog.cxx \
Fl_ICO_Image.cxx \
Fl_JPEG_Image.cxx \
+3 -1
View File
@@ -27,6 +27,7 @@
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_BMP_Image.H>
#include <FL/Fl_GIF_Image.H>
#include <FL/Fl_Anim_GIF_Image.H>
#include <FL/Fl_JPEG_Image.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/Fl_PNM_Image.H>
@@ -89,7 +90,8 @@ fl_check_images(const char *name, // I - Filename
if (memcmp(header, "GIF87a", 6) == 0 ||
memcmp(header, "GIF89a", 6) == 0) // GIF file
return new Fl_GIF_Image(name);
return Fl_GIF_Image::animate ? new Fl_Anim_GIF_Image(name) :
new Fl_GIF_Image(name);
// BMP
+5
View File
@@ -1954,6 +1954,11 @@ Fl_get_system_colors.o: flstring.h
Fl_get_system_colors.o: Fl_Screen_Driver.H
Fl_get_system_colors.o: Fl_System_Driver.H
Fl_get_system_colors.o: tile.xpm
Fl_Anim_GIF_Image.o: ../config.h
Fl_Anim_GIF_Image.o: ../FL/Fl_Anim_GIF_Image.H
Fl_Anim_GIF_Image.o: ../FL/Fl_GIF_Image.H
Fl_Anim_GIF_Image.o: ../FL/Fl_Image.H
Fl_Anim_GIF_Image.o: ../FL/Fl_Pixmap.H
Fl_GIF_Image.o: ../config.h
Fl_GIF_Image.o: ../FL/Enumerations.H
Fl_GIF_Image.o: ../FL/Fl.H
+1 -1
View File
@@ -113,7 +113,7 @@ CREATE_EXAMPLE (navigation navigation.cxx fltk)
CREATE_EXAMPLE (output output.cxx fltk)
CREATE_EXAMPLE (overlay overlay.cxx fltk)
CREATE_EXAMPLE (pack pack.cxx fltk)
CREATE_EXAMPLE (pixmap pixmap.cxx fltk)
CREATE_EXAMPLE (pixmap pixmap.cxx "fltk_images;fltk")
CREATE_EXAMPLE (pixmap_browser pixmap_browser.cxx "fltk_images;fltk")
CREATE_EXAMPLE (preferences preferences.fl fltk)
CREATE_EXAMPLE (offscreen offscreen.cxx fltk)
+4 -1
View File
@@ -512,7 +512,10 @@ overlay$(EXEEXT): overlay.o
pack$(EXEEXT): pack.o
pixmap$(EXEEXT): pixmap.o
pixmap$(EXEEXT): pixmap.o $(IMGLIBNAME)
echo Linking $@...
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ pixmap.o $(LINKFLTKIMG) $(LDLIBS)
$(OSX_ONLY) ../fltk-config --post $@
pixmap_browser$(EXEEXT): pixmap_browser.o $(IMGLIBNAME)
echo Linking $@...
+11
View File
@@ -24,9 +24,18 @@
//
#include <FL/Fl_Help_Dialog.H>
#include <FL/Fl_GIF_Image.H>
#include <FL/filename.H> /* FL_PATH_MAX */
#include <FL/Fl.H> /* Fl::first_window(), etc */
#include <string.h> /* strcpy(), etc */
static void cb_refresh(void *d) {
// trigger a redraw of the window to see animated GIF's
if (Fl::first_window())
Fl::first_window()->redraw();
Fl::repeat_timeout(1./10, cb_refresh, d);
}
//
// 'main()' - Display the help GUI...
//
@@ -35,6 +44,7 @@ int // O - Exit status
main(int argc, // I - Number of command-line arguments
char *argv[]) // I - Command-line arguments
{
Fl_GIF_Image::animate = true; // create animated shared .GIF images
Fl_Help_Dialog *help = new Fl_Help_Dialog;
int i;
if (!Fl::args(argc, argv, i)) Fl::fatal(Fl::help);
@@ -44,6 +54,7 @@ main(int argc, // I - Number of command-line arguments
help->show(1, argv);
Fl::add_timeout(1./10, cb_refresh, help); // to animate GIF's
Fl::run();
delete help;
+3
View File
@@ -263,6 +263,9 @@ Nested OL/UL:
</TR><TR>
<TD><IMG SRC="images/tiny.png" alt="Tiny FLTK logo"></TD>
<TD>Tiny FLTK logo.</TD>
</TR><TR>
<TD><IMG SRC="pixmaps/fltk_animated.gif" WIDTH="200" HEIGHT="50" alt="Animated FLTK logo"></TD>
<TD>Animated FLTK logo.</TD>
</TR><TR>
<TD><IMG SRC="images/Fl_Value_Input.png" alt="Fl_Value_Input"></TD>
<TD>This is an image of Fl_Value_Input</TD>
+44 -10
View File
@@ -18,17 +18,20 @@
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Anim_GIF_Image.H>
#include <stdio.h>
#include "pixmaps/porsche.xpm"
#include "pixmaps/animated_fluid_gif.h"
#include <FL/Fl_Toggle_Button.H>
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb;
Fl_Button *b;
Fl_Double_Window *w;
Fl_Anim_GIF_Image *pixmap;
Fl_Anim_GIF_Image *depixmap;
void button_cb(Fl_Widget *,void *) {
void button_cb(Fl_Widget *wgt,void *) {
int i = 0;
if (leftb->value()) i |= FL_ALIGN_LEFT;
if (rightb->value()) i |= FL_ALIGN_RIGHT;
@@ -42,6 +45,21 @@ void button_cb(Fl_Widget *,void *) {
w->redraw();
}
void play_cb(Fl_Widget *wgt,void *) {
pixmap->start();
depixmap->start();
}
void stop_cb(Fl_Widget *wgt,void *) {
pixmap->stop();
depixmap->stop();
}
void step_cb(Fl_Widget *wgt,void *) {
pixmap->next();
depixmap->next();
}
int dvisual = 0;
int arg(int, char **argv, int &i) {
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
@@ -53,18 +71,24 @@ int arg(int, char **argv, int &i) {
int main(int argc, char **argv) {
int i = 1;
if (Fl::args(argc,argv,i,arg) < argc)
Fl::fatal(" -8 # : use default visual\n%s\n",Fl::help);
Fl::fatal(" -8 # : use default visual\n%s\n", Fl::help);
if (!dvisual) Fl::visual(FL_RGB);
Fl_Double_Window window(400,400); ::w = &window;
Fl_Button b(140,160,120,120,"Pixmap"); ::b = &b;
Fl_Pixmap *pixmap = new Fl_Pixmap(porsche_xpm);
Fl_Pixmap *depixmap;
depixmap = (Fl_Pixmap *)pixmap->copy();
Fl_Double_Window window(400,440); ::w = &window;
Fl_Button b(130,170,140,140,"Pixmap"); ::b = &b;
Fl_Anim_GIF_Image::animate = true;
pixmap = new Fl_Anim_GIF_Image("fluid", animated_fluid_gif, animated_fluid_gif_size,
&b, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
pixmap->speed(0.5);
b.image(pixmap);
depixmap = (Fl_Anim_GIF_Image*)pixmap->copy();
depixmap->inactive();
b.deimage(depixmap);
// "bind" images to avoid memory leak reports (valgrind, asan)
// note: these reports are benign because they appear at exit, but anyway
b.bind_image(pixmap);
b.bind_deimage(depixmap);
@@ -82,7 +106,17 @@ int main(int argc, char **argv) {
overb->callback(button_cb);
inactb = new Fl_Toggle_Button(125,75,100,25,"inactive");
inactb->callback(button_cb);
if (!dvisual) Fl::visual(FL_RGB);
Fl_Button* play = new Fl_Button(300, 50, 25, 25, "@>");
play->labelcolor(FL_DARK2);
play->callback(play_cb);
Fl_Button* stop = new Fl_Button(325, 50, 25, 25, "@||");
stop->labelcolor(FL_DARK2);
stop->callback(stop_cb);
Fl_Button* step = new Fl_Button(350, 50, 25, 25, "@|>");
step->labelcolor(FL_DARK2);
step->callback(step_cb);
window.resizable(window);
window.end();
window.show(argc,argv);
+19
View File
@@ -20,6 +20,7 @@
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_GIF_Image.H>
#include <FL/Fl_Printer.H>
#include <string.h>
#include <errno.h>
@@ -36,6 +37,17 @@ Fl_Shared_Image *img;
static char name[1024];
void cb_forced_redraw(void *) {
Fl_Window *win = Fl::first_window();
while (win) {
if (!win->menu_window())
win->redraw();
win = Fl::next_window(win);
}
if (Fl::first_window())
Fl::repeat_timeout(1./10, cb_forced_redraw);
}
void load_file(const char *n) {
if (img) {
((Fl_Shared_Image*)b->image())->release();
@@ -118,8 +130,10 @@ void svg_cb(Fl_Widget *widget, void *) {
}
int dvisual = 0;
int animate = 1;
int arg(int, char **argv, int &i) {
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
if (argv[i][1] == 'a') {animate = 1; i++; return 1;}
return 0;
}
@@ -131,6 +145,9 @@ int main(int argc, char **argv) {
Fl::args(argc,argv,i,arg);
if (animate)
Fl_GIF_Image::animate = true; // create animated shared .GIF images (e.g. file chooser)
Fl_Double_Window window(400,450); ::w = &window;
Fl_Box b(10,45,380,380); ::b = &b;
b.box(FL_THIN_DOWN_BOX);
@@ -146,5 +163,7 @@ int main(int argc, char **argv) {
svg.callback(svg_cb);
window.show(argc,argv);
if (animate)
Fl::add_timeout(1./10, cb_forced_redraw); // force periodic redraw
return Fl::run();
}
+118
View File
@@ -0,0 +1,118 @@
static const size_t animated_fluid_gif_size = 2545;
static const unsigned char animated_fluid_gif[] =
{71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80,
77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254,
0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91,
161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108,
182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69,
84,83,67,65,80,69,50,46,48,3,1,0,0,0,33,249,4,5,10,0,31,0,44,0,0,0,0,96,0,96,0,
0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223,
120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201,
91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147,
241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28,
93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143,
90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153,
142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64,
188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120,
25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231,
105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218,
161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193,
232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254,
81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121,
51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163,
237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109,
100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72,
177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78,
83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195,
61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107,
246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250,
234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208,
216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103,
106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191,
255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16,
70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195,
0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98,
192,160,20,7,214,215,16,15,46,54,136,65,3,12,36,160,0,2,20,76,128,0,144,61,122,
120,65,3,9,84,112,227,139,8,28,144,0,3,10,56,41,133,4,57,182,183,98,15,16,60,88,
129,2,11,20,48,193,2,11,8,73,38,3,17,60,217,33,2,103,166,9,33,6,19,48,64,166,2,
110,74,145,162,150,27,241,64,226,131,114,162,201,166,2,14,200,185,64,3,117,118,
120,193,1,115,66,160,166,131,9,144,153,64,161,98,92,104,15,139,139,82,64,38,2,
16,68,48,1,5,16,128,25,38,164,28,126,57,36,168,82,92,32,40,166,139,102,137,39,
76,25,202,40,232,3,105,74,32,65,5,115,58,32,43,141,18,144,42,5,173,11,0,10,42,
150,58,62,197,67,151,47,38,170,225,140,108,150,169,40,174,183,74,152,172,2,138,
46,58,133,164,42,254,68,225,96,5,19,52,112,38,2,19,220,216,232,2,168,74,128,65,
145,7,80,192,32,156,155,58,152,65,5,69,54,43,5,5,9,36,48,193,183,13,44,27,225,
48,42,10,11,192,158,14,206,235,169,2,65,106,136,129,167,176,86,32,40,153,182,
90,128,232,160,26,82,224,233,160,79,98,208,232,144,7,23,96,111,132,170,202,224,
131,180,22,152,74,166,197,178,74,96,105,175,209,122,188,0,154,12,10,58,65,154,
23,12,76,230,202,231,202,233,235,152,189,218,202,177,20,17,100,105,144,158,18,
186,188,128,3,246,46,92,47,131,38,31,160,40,175,63,187,233,51,172,82,124,91,64,
154,52,51,144,233,134,22,246,101,109,132,35,51,96,179,20,130,62,205,32,175,10,
192,122,65,178,82,19,157,245,212,52,39,144,169,4,218,46,96,244,205,14,226,187,
234,125,20,38,171,246,141,24,144,249,243,178,81,71,43,232,219,82,180,253,54,6,
42,47,75,176,174,16,234,204,42,15,27,126,139,64,157,125,223,40,184,162,35,47,0,
235,141,93,67,109,172,5,35,67,235,238,134,254,146,250,144,100,132,135,75,78,38,
224,25,148,254,45,180,46,130,237,128,134,223,222,205,182,163,203,194,237,224,
157,62,177,184,97,222,100,70,219,177,167,94,115,158,168,4,19,120,58,180,20,125,
71,112,129,167,143,139,203,252,197,29,202,109,20,15,11,110,120,118,235,181,62,
112,128,5,52,215,27,168,227,16,32,192,224,228,13,60,160,55,200,109,91,94,0,5,38,
2,59,142,238,28,78,126,35,205,128,54,57,187,219,129,82,208,117,3,221,90,0,252,
1,7,144,128,167,140,118,36,48,133,13,101,237,59,141,15,136,213,184,143,65,78,
111,10,40,128,172,210,55,36,1,206,233,81,12,122,24,6,41,152,0,243,205,233,1,159,
235,16,238,234,48,162,14,185,204,115,13,50,216,201,130,247,165,147,193,12,81,10,
120,27,131,254,212,128,215,137,75,91,10,168,87,4,26,197,128,203,209,104,18,82,
185,218,134,120,165,67,7,229,42,86,13,58,34,18,143,232,174,92,133,236,74,76,12,
89,4,88,246,67,11,232,140,82,20,194,128,147,46,64,51,31,62,232,86,79,122,148,
226,141,158,104,196,207,49,72,2,51,234,216,25,171,104,129,170,253,32,0,27,146,
147,248,26,37,59,54,218,241,142,86,36,2,28,41,68,166,6,208,202,87,182,195,163,
32,39,164,42,234,109,8,1,10,152,82,15,17,55,200,70,74,168,144,10,226,144,3,40,
96,195,16,58,242,146,247,210,99,135,66,22,72,76,98,18,146,0,128,158,39,71,121,
34,9,224,238,141,1,72,165,42,87,201,202,86,186,242,149,176,140,165,44,103,201,
202,31,144,176,9,184,204,165,46,119,201,203,94,246,82,36,190,12,166,48,135,73,
76,34,76,175,152,200,76,102,49,75,16,2,0,33,249,4,5,10,0,31,0,44,30,0,4,0,38,0,
57,0,0,5,254,224,39,142,31,96,158,104,170,2,100,235,174,112,236,206,174,103,
223,56,158,210,60,205,113,185,91,111,152,201,136,56,25,100,50,232,25,246,126,71,
227,143,233,57,57,121,72,13,105,169,51,93,105,154,204,141,243,225,222,172,95,
151,70,227,209,126,128,65,116,186,85,92,127,168,115,44,156,218,204,147,236,111,
100,83,113,94,126,128,69,101,98,132,44,115,124,124,114,126,45,123,57,145,88,102,
56,149,60,110,153,156,157,158,159,160,161,162,149,142,120,145,165,76,164,168,
148,167,171,152,173,174,54,170,177,125,126,180,178,176,177,179,76,28,107,26,100,
163,34,97,69,69,192,162,74,196,197,163,201,201,155,160,204,196,206,159,208,117,
163,195,204,198,160,200,209,66,161,189,35,147,184,78,183,169,227,228,229,78,189,
191,231,226,62,208,225,186,154,208,108,231,150,212,240,174,238,247,236,181,36,
219,201,217,60,253,35,22,80,224,187,96,111,0,130,226,199,176,161,67,90,219,128,
61,196,49,144,204,68,27,3,139,93,244,144,49,137,175,143,32,67,138,244,149,225,
130,201,147,38,3,51,132,0,0,33,249,4,5,10,0,31,0,44,34,0,7,0,34,0,54,0,0,5,202,
224,39,138,94,105,158,168,57,174,236,154,190,104,43,143,112,237,205,179,13,227,
178,254,242,45,95,10,200,18,198,136,52,163,10,73,82,150,152,77,39,116,74,141,42,
167,206,39,52,123,171,122,191,224,176,120,76,46,155,207,232,244,151,195,230,156,
57,154,140,60,227,94,107,52,245,185,190,62,229,232,229,113,127,114,85,129,130,
134,83,1,126,130,23,134,25,136,138,127,140,135,80,137,141,134,124,76,144,127,
112,43,28,90,80,154,114,158,30,109,163,93,125,123,58,72,92,75,64,172,39,106,177,
76,175,63,69,175,112,119,152,46,172,133,162,61,92,161,190,182,89,141,26,65,92,
197,199,196,134,198,195,78,189,115,186,31,172,193,205,100,112,209,68,144,120,
102,208,116,180,90,193,25,26,224,93,222,114,229,34,231,25,233,31,25,23,240,241,
240,119,244,245,246,247,244,33,0,33,249,4,5,10,0,31,0,44,36,0,13,0,26,0,48,0,0,
5,196,224,39,138,156,102,114,99,170,174,100,230,186,26,43,143,220,107,163,243,
26,104,182,157,235,188,158,235,167,218,9,135,196,84,77,24,75,166,130,55,167,
106,153,209,224,164,88,44,103,123,205,150,162,217,207,177,155,164,246,178,208,
51,54,237,211,30,51,225,177,103,78,247,252,190,175,79,189,46,219,115,57,123,
124,44,129,132,123,125,133,136,42,0,139,136,137,41,139,0,141,30,93,100,31,144,
141,102,46,28,1,131,133,98,71,14,157,132,153,47,26,156,41,152,111,149,57,164,
154,104,76,97,164,171,101,39,78,84,86,97,31,108,25,128,146,83,71,26,146,118,79,
111,194,42,187,46,198,196,71,202,52,114,190,191,54,193,205,74,38,86,194,216,217,
218,219,136,102,171,194,178,43,146,173,188,42,227,170,199,214,234,214,25,23,238,
239,238,112,41,33,0,33,249,4,5,10,0,31,0,44,38,0,5,0,21,0,56,0,0,5,232,224,39,
142,80,52,158,104,202,101,25,151,190,98,166,105,172,11,167,44,171,125,156,125,
139,171,26,173,245,27,245,56,195,93,17,185,11,250,96,131,97,203,89,20,205,106,
181,170,199,99,67,102,127,219,174,231,11,3,132,129,231,159,57,204,217,186,223,
111,145,185,7,175,199,81,109,207,76,249,91,105,182,82,79,48,109,121,71,85,64,68,
135,39,52,127,112,76,26,130,136,132,133,57,58,47,121,34,92,149,57,28,1,153,118,
122,155,57,3,159,118,82,155,164,31,160,161,162,25,169,171,65,155,26,175,171,167,
53,158,170,171,154,58,79,186,160,138,192,193,194,39,190,118,55,73,160,0,0,120,
162,121,111,2,56,173,117,27,203,70,173,45,117,204,173,206,110,218,205,198,39,
215,191,39,177,156,197,110,73,96,231,235,117,71,189,190,167,124,240,162,74,186,
229,149,46,246,215,249,176,251,185,160,247,56,85,177,37,67,81,188,17,231,220,17,
99,199,176,225,186,61,16,35,74,220,19,2,0,59};
Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

+2 -3
View File
@@ -47,11 +47,10 @@ int arg(int argc, char **argv, int &i) {
}
int main(int argc, char **argv) {
#ifdef FLTK_USE_X11
int i = 1;
Fl::args(argc,argv,i,arg);
#ifdef FLTK_USE_X11
if (visid >= 0) {
fl_open_display();
XVisualInfo templt; int num;
+2 -2
View File
@@ -609,7 +609,7 @@ int main(int argc, char** argv)
end_list /= 16;
}
argc = 1;
for (long y = off; y < end_list; y++) {
for (int y = off; y < end_list; y++) {
int o = 0;
char bu[25]; // index label
char buf[16 * 6]; // utf8 text
@@ -622,7 +622,7 @@ int main(int argc, char** argv)
i++;
}
buf[o] = '\0';
snprintf(bu, sizeof(bu), "0x%06lX", y * 16);
snprintf(bu, sizeof(bu), "0x%06X", y * 16);
Fl_Input *b = new Fl_Input(200,(y-off)*25,80,25);
b->textfont(FL_COURIER);
b->value(fl_strdup(bu));