mirror of https://github.com/fltk/fltk
Animated GIF support (Fl_Anim_GIF_Image class) (#375)
This commit is contained in:
parent
1fc269b0d4
commit
2ddfd9d949
|
@ -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
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// GIF image header file for the Fast Light Tool Kit (FLTK).
|
// 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
|
// 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
|
// 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)
|
// constructor with length (since 1.4.0)
|
||||||
Fl_GIF_Image(const char* imagename, const unsigned char *data, const size_t length);
|
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:
|
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
|
#endif
|
||||||
|
|
|
@ -272,6 +272,9 @@ public:
|
||||||
|
|
||||||
An internal copy is made of the original image before
|
An internal copy is made of the original image before
|
||||||
changes are applied, to avoid modifying the original image.
|
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); }
|
void inactive() { color_average(FL_GRAY, .33f); }
|
||||||
virtual void desaturate();
|
virtual void desaturate();
|
||||||
|
|
|
@ -81,6 +81,10 @@ set (FLUID_SOURCES
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
set (IMAGE_SOURCES
|
set (IMAGE_SOURCES
|
||||||
|
animgifimage
|
||||||
|
animgifimage-play
|
||||||
|
animgifimage-resize
|
||||||
|
animgifimage-simple
|
||||||
howto-simple-svg
|
howto-simple-svg
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,11 @@ SHELL = /bin/sh
|
||||||
.SILENT:
|
.SILENT:
|
||||||
|
|
||||||
# Executables
|
# Executables
|
||||||
ALL = browser-simple$(EXEEXT) \
|
ALL = animgifimage$(EXEEXT) \
|
||||||
|
animgifimage-play$(EXEEXT) \
|
||||||
|
animgifimage-simple$(EXEEXT) \
|
||||||
|
animgifimage-resize$(EXEEXT) \
|
||||||
|
browser-simple$(EXEEXT) \
|
||||||
cairo-draw-x$(EXEEXT) \
|
cairo-draw-x$(EXEEXT) \
|
||||||
chart-simple$(EXEEXT) \
|
chart-simple$(EXEEXT) \
|
||||||
draggable-group$(EXEEXT) \
|
draggable-group$(EXEEXT) \
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -30,6 +30,7 @@
|
||||||
#include <FL/fl_utf8.h> // fl_fopen()
|
#include <FL/fl_utf8.h> // fl_fopen()
|
||||||
#include <FL/Fl_File_Chooser.H>
|
#include <FL/Fl_File_Chooser.H>
|
||||||
#include <FL/Fl_SVG_Image.H>
|
#include <FL/Fl_SVG_Image.H>
|
||||||
|
#include <FL/Fl_Anim_GIF_Image.H>
|
||||||
#include "../src/flstring.h"
|
#include "../src/flstring.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -51,6 +52,7 @@ static int image_header_written = 0;
|
||||||
static int jpeg_header_written = 0;
|
static int jpeg_header_written = 0;
|
||||||
static int png_header_written = 0;
|
static int png_header_written = 0;
|
||||||
static int gif_header_written = 0;
|
static int gif_header_written = 0;
|
||||||
|
static int animated_gif_header_written = 0;
|
||||||
static int bmp_header_written = 0;
|
static int bmp_header_written = 0;
|
||||||
static int svg_header_written = 0;
|
static int svg_header_written = 0;
|
||||||
|
|
||||||
|
@ -134,8 +136,19 @@ void Fluid_Image::write_static(int compressed) {
|
||||||
if (!img) return;
|
if (!img) return;
|
||||||
const char *idata_name = unique_id(this, "idata", fl_filename_name(name()), 0);
|
const char *idata_name = unique_id(this, "idata", fl_filename_name(name()), 0);
|
||||||
function_name_ = unique_id(this, "image", 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 gif image data...
|
||||||
write_c("\n");
|
write_c("\n");
|
||||||
if (gif_header_written != write_number) {
|
if (gif_header_written != write_number) {
|
||||||
|
@ -146,7 +159,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||||
size_t nData = write_static_binary("GIF");
|
size_t nData = write_static_binary("GIF");
|
||||||
write_c(";\n");
|
write_c(";\n");
|
||||||
write_initializer("Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
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 bmp image data...
|
||||||
write_c("\n");
|
write_c("\n");
|
||||||
if (bmp_header_written != write_number) {
|
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_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h());
|
||||||
write_c(";\n");
|
write_c(";\n");
|
||||||
write_initializer( "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h());
|
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 jpeg image data...
|
||||||
write_c("\n");
|
write_c("\n");
|
||||||
if (jpeg_header_written != write_number) {
|
if (jpeg_header_written != write_number) {
|
||||||
|
@ -209,7 +222,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||||
size_t nData = write_static_binary("JPEG");
|
size_t nData = write_static_binary("JPEG");
|
||||||
write_c(";\n");
|
write_c(";\n");
|
||||||
write_initializer("Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
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 png image data...
|
||||||
write_c("\n");
|
write_c("\n");
|
||||||
if (png_header_written != write_number) {
|
if (png_header_written != write_number) {
|
||||||
|
@ -220,7 +233,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||||
size_t nData = write_static_binary("PNG");
|
size_t nData = write_static_binary("PNG");
|
||||||
write_c(";\n");
|
write_c(";\n");
|
||||||
write_initializer("Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
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);
|
bool gzipped = (strcmp(fl_filename_ext(name()), ".svgz") == 0);
|
||||||
// Write svg image data...
|
// Write svg image data...
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
|
@ -242,7 +255,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if FLUID runs from the command line, make sure that the image is not
|
// 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_RGB_Image* rgb_image = NULL;
|
||||||
Fl_SVG_Image* svg_image = NULL;
|
Fl_SVG_Image* svg_image = NULL;
|
||||||
if (img->d()>0)
|
if (img->d()>0)
|
||||||
|
@ -279,6 +292,8 @@ void Fluid_Image::write_initializer(const char *type_name, const char *format, .
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
write_c("static Fl_Image *%s() {\n", function_name_);
|
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("%sstatic Fl_Image *image = NULL;\n", indent(1));
|
||||||
write_c("%sif (!image)\n", indent(1));
|
write_c("%sif (!image)\n", indent(1));
|
||||||
write_c("%simage = new %s(", indent(2), type_name);
|
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) {
|
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.
|
/* 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() */
|
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) {
|
void Fluid_Image::write_inline(int inactive) {
|
||||||
|
@ -355,11 +374,20 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fluid_Image::Fluid_Image(const char *iname) {
|
Fluid_Image::Fluid_Image(const char *iname)
|
||||||
|
: is_animated_gif_(false)
|
||||||
|
{
|
||||||
name_ = fl_strdup(iname);
|
name_ = fl_strdup(iname);
|
||||||
written = 0;
|
written = 0;
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
img = Fl_Shared_Image::get(iname);
|
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;
|
function_name_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <FL/Fl_Shared_Image.H>
|
#include <FL/Fl_Shared_Image.H>
|
||||||
|
|
||||||
class Fluid_Image {
|
class Fluid_Image {
|
||||||
|
bool is_animated_gif_;
|
||||||
const char *name_;
|
const char *name_;
|
||||||
int refcount;
|
int refcount;
|
||||||
Fl_Shared_Image *img;
|
Fl_Shared_Image *img;
|
||||||
|
|
|
@ -21,236 +21,127 @@ void show_help(const char *name);
|
||||||
|
|
||||||
Fl_Double_Window *about_panel=(Fl_Double_Window *)0;
|
Fl_Double_Window *about_panel=(Fl_Double_Window *)0;
|
||||||
|
|
||||||
#include <FL/Fl_Pixmap.H>
|
#include <FL/Fl_Anim_GIF_Image.H>
|
||||||
static const char *idata_fluid[] = {
|
static const unsigned char idata_fluid[] =
|
||||||
"96 96 32 1",
|
{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,
|
||||||
" \tc None",
|
77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254,
|
||||||
".\tc #000100",
|
0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91,
|
||||||
"+\tc #031F3F",
|
161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108,
|
||||||
"@\tc #00366C",
|
182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69,
|
||||||
"#\tc #2E302D",
|
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,
|
||||||
"$\tc #0058AC",
|
0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223,
|
||||||
"%\tc #0060BF",
|
120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201,
|
||||||
"&\tc #4E504D",
|
91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147,
|
||||||
"*\tc #14659F",
|
241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28,
|
||||||
"=\tc #006DDC",
|
93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143,
|
||||||
"-\tc #2C7087",
|
90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153,
|
||||||
";\tc #0080FF",
|
142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64,
|
||||||
">\tc #407B74",
|
188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120,
|
||||||
",\tc #0F85F9",
|
25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231,
|
||||||
"\'\tc #268CCD",
|
105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218,
|
||||||
")\tc #7C7E7B",
|
161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193,
|
||||||
"!\tc #2D92EC",
|
232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254,
|
||||||
"~\tc #4498A9",
|
81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121,
|
||||||
"{\tc #2F94FE",
|
51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163,
|
||||||
"]\tc #5BA18C",
|
237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109,
|
||||||
"^\tc #6BA674",
|
100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72,
|
||||||
"/\tc #7DAD62",
|
177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78,
|
||||||
"(\tc #93BD53",
|
83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195,
|
||||||
"_\tc #A4A6A2",
|
61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107,
|
||||||
":\tc #6CB6FF",
|
246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250,
|
||||||
"<\tc #ABCC3F",
|
234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208,
|
||||||
"[\tc #C4DA2A",
|
216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103,
|
||||||
"}\tc #CACCC9",
|
106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191,
|
||||||
"|\tc #DCE913",
|
255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16,
|
||||||
"1\tc #BBDEFF",
|
70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195,
|
||||||
"2\tc #FDFE00",
|
0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98,
|
||||||
"3\tc #FDFFFC",
|
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,
|
||||||
" ....)__}33333333333}_... \
|
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,
|
||||||
" ...&33333333333333333... \
|
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,
|
||||||
" ...#33311133333333333... \
|
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,
|
||||||
" ...&33!,{,;:333333333... \
|
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,
|
||||||
" ...&3:,{{{{,13333333}... \
|
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,
|
||||||
" ...&3!{{!{{,13333333}... \
|
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,
|
||||||
" ...&3:!{{!{;13333333}... \
|
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,
|
||||||
" ...&3{{{{{{;133333333... \
|
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,
|
||||||
" ...&31,{{{;,33333333}... \
|
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,
|
||||||
" ...&331{{{:133333333}... \
|
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,
|
||||||
" ...&3333333333333333_... \
|
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,
|
||||||
" ...&3333333333333333}... \
|
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,
|
||||||
" ...&3333333333333333_... \
|
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,
|
||||||
" ...&3333333333333333}... \
|
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,
|
||||||
" ...&3333333333333333_... \
|
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,
|
||||||
" ...&3333333333333333}... \
|
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,
|
||||||
" ...&3333333333333333_... \
|
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,
|
||||||
" ...&3333333331!,,;:3}... \
|
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,
|
||||||
" ...&333333333{{{{{;:_... \
|
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,
|
||||||
" ...&333333331,{!{!{{}... \
|
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,
|
||||||
" ...&333333331{{{{{{,_... \
|
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,
|
||||||
" ...)333333331{{!{{{{_... \
|
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,
|
||||||
" ...)333333333{{{!{;:_... \
|
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,
|
||||||
" ...)3333333331{;;;:3_... \
|
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,
|
||||||
" ...)3333333333331333_... \
|
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,
|
||||||
" ...)3333333333333333_... \
|
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,
|
||||||
" ...)3333333333333333_... \
|
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,
|
||||||
" ..._3333333333333333_... \
|
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,
|
||||||
" ..._3333333333333333_... \
|
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,
|
||||||
" ..._3333333333333333_... \
|
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,
|
||||||
" ..._3333333333333333}.... \
|
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,
|
||||||
" ...._33333333333333333#... \
|
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,
|
||||||
" ....&333333333333333333_.... \
|
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,
|
||||||
" ....&33333333333333333333).... \
|
99,199,176,225,186,61,16,35,74,220,19,2,0,59};
|
||||||
",
|
|
||||||
" ....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|*%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
|
||||||
;;;;;;;;;;;;;;;;+...",
|
|
||||||
"...+;;;;;;;;;;;^|<[[-%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
|
||||||
;;;;;;;;;;;;;;;+...",
|
|
||||||
"...+;;;;;;;;;;;;*~*%===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
|
||||||
;;;;;;;;;;;;;;;@...",
|
|
||||||
"...+;;;;;;;;;;;;;====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
|
||||||
;;;;;;;;;;;;;;;+...",
|
|
||||||
"....$=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
|
||||||
;;;;;;;;;;;;;=$....",
|
|
||||||
" .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\
|
|
||||||
+++++++++++++..... ",
|
|
||||||
" ............................................................................\
|
|
||||||
................. ",
|
|
||||||
" ...........................................................................\
|
|
||||||
................. ",
|
|
||||||
" ........................................................................\
|
|
||||||
.............. "
|
|
||||||
};
|
|
||||||
static Fl_Image *image_fluid() {
|
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;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +166,8 @@ Fl_Double_Window* make_about_panel() {
|
||||||
about_panel->hotspot(about_panel);
|
about_panel->hotspot(about_panel);
|
||||||
{ Fl_Box* o = new Fl_Box(10, 10, 115, 120);
|
{ Fl_Box* o = new Fl_Box(10, 10, 115, 120);
|
||||||
o->image( image_fluid() );
|
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
|
||||||
{ Fl_Box* o = new Fl_Box(135, 10, 205, 75, "FLTK User\nInterface Designer\nVersion x.x.x");
|
{ Fl_Box* o = new Fl_Box(135, 10, 205, 75, "FLTK User\nInterface Designer\nVersion x.x.x");
|
||||||
o->color((Fl_Color)12);
|
o->color((Fl_Color)12);
|
||||||
|
|
|
@ -36,11 +36,12 @@ if (!cbuf[0]) {
|
||||||
}} {}
|
}} {}
|
||||||
Fl_Window about_panel {
|
Fl_Window about_panel {
|
||||||
label {About FLUID} open
|
label {About FLUID} open
|
||||||
xywh {449 217 345 180} type Double color 50 selection_color 47 hide hotspot
|
xywh {449 217 345 180} type Double color 50 selection_color 47 hotspot
|
||||||
code0 {\#include "../src/flstring.h"} non_modal
|
code0 {\#include "../src/flstring.h"} non_modal visible
|
||||||
} {
|
} {
|
||||||
Fl_Box {} {
|
Fl_Box {} {selected
|
||||||
image {icons/fluid-96.xpm} xywh {10 10 115 120}
|
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 {} {
|
Fl_Box {} {
|
||||||
label {FLTK User
|
label {FLTK User
|
||||||
|
@ -59,7 +60,7 @@ Version x.x.x}
|
||||||
}
|
}
|
||||||
Fl_Button {} {
|
Fl_Button {} {
|
||||||
label {View License...}
|
label {View License...}
|
||||||
callback {show_help("license.html");} selected
|
callback {show_help("license.html");}
|
||||||
xywh {115 145 123 25} labelcolor 136
|
xywh {115 145 123 25} labelcolor 136
|
||||||
}
|
}
|
||||||
Fl_Return_Button {} {
|
Fl_Return_Button {} {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
|
@ -471,6 +471,7 @@ set (IMGCPPFILES
|
||||||
Fl_BMP_Image.cxx
|
Fl_BMP_Image.cxx
|
||||||
Fl_File_Icon2.cxx
|
Fl_File_Icon2.cxx
|
||||||
Fl_GIF_Image.cxx
|
Fl_GIF_Image.cxx
|
||||||
|
Fl_Anim_GIF_Image.cxx
|
||||||
Fl_Help_Dialog.cxx
|
Fl_Help_Dialog.cxx
|
||||||
Fl_ICO_Image.cxx
|
Fl_ICO_Image.cxx
|
||||||
Fl_JPEG_Image.cxx
|
Fl_JPEG_Image.cxx
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// Fl_GIF_Image routines.
|
// Fl_GIF_Image routines.
|
||||||
//
|
//
|
||||||
// Copyright 1997-2021 by Bill Spitzak and others.
|
// Copyright 1997-2023 by Bill Spitzak and others.
|
||||||
//
|
//
|
||||||
// This library is free software. Distribution and use rights are outlined in
|
// 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
|
// the file "COPYING" which should have been included with this file. If this
|
||||||
|
@ -73,6 +73,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internally used structure to hold GIF color map data
|
||||||
|
during decoding.
|
||||||
|
*/
|
||||||
|
struct ColorMap {
|
||||||
|
uchar Red[256];
|
||||||
|
uchar Green[256];
|
||||||
|
uchar Blue[256];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This small helper function checks for read errors or end of file
|
This small helper function checks for read errors or end of file
|
||||||
and does some cleanup if an error was found.
|
and does some cleanup if an error was found.
|
||||||
|
@ -137,8 +147,8 @@ Fl_GIF_Image::Fl_GIF_Image(const char *filename) :
|
||||||
|
|
||||||
Construct an image from a block of memory inside the application. Fluid offers
|
Construct an image from a block of memory inside the application. Fluid offers
|
||||||
"binary data" chunks as a great way to add image data into the C++ source code.
|
"binary data" chunks as a great way to add image data into the C++ source code.
|
||||||
\p imagename can be NULL. If a name is given, the image is added to the list of
|
\p imagename can be \c NULL. If a name is given, the image is added to the
|
||||||
shared images and will be available by that name.
|
list of shared images and will be available by that name.
|
||||||
|
|
||||||
If a GIF image is animated, Fl_GIF_Image will only read and display the
|
If a GIF image is animated, Fl_GIF_Image will only read and display the
|
||||||
first frame of the animation.
|
first frame of the animation.
|
||||||
|
@ -205,193 +215,49 @@ Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Fl_GIF_Image::Fl_GIF_Image(const char *filename, bool anim) :
|
||||||
This method reads GIF image data and creates an RGB or RGBA image. The GIF
|
Fl_Pixmap((char *const*)0)
|
||||||
format supports only 1 bit for alpha. The final image data is stored in
|
|
||||||
a modified XPM format (Fl_GIF_Image is a subclass of Fl_Pixmap).
|
|
||||||
To avoid code duplication, we use an Fl_Image_Reader that reads data from
|
|
||||||
either a file or from memory.
|
|
||||||
*/
|
|
||||||
void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
|
||||||
{
|
{
|
||||||
char **new_data; // Data array
|
Fl_Image_Reader rdr;
|
||||||
uchar *Image = 0L; // internal temporary image data array
|
if (rdr.open(filename) == -1) {
|
||||||
w(0); h(0);
|
Fl::error("Fl_GIF_Image: Unable to open %s!", filename);
|
||||||
|
ld(ERR_FILE_ACCESS);
|
||||||
// printf("\nFl_GIF_Image::load_gif_ : %s\n", rdr.name());
|
|
||||||
|
|
||||||
{char b[6] = { 0 };
|
|
||||||
for (int i=0; i<6; ++i) b[i] = rdr.read_byte();
|
|
||||||
if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
|
|
||||||
Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", rdr.name());
|
|
||||||
ld(ERR_FORMAT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
|
|
||||||
Fl::warning("%s is version %c%c%c.",rdr.name(),b[3],b[4],b[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Width = rdr.read_word();
|
|
||||||
int Height = rdr.read_word();
|
|
||||||
|
|
||||||
uchar ch = rdr.read_byte();
|
|
||||||
CHECK_ERROR
|
|
||||||
char HasColormap = ((ch & 0x80) != 0);
|
|
||||||
int BitsPerPixel = (ch & 7) + 1;
|
|
||||||
int ColorMapSize;
|
|
||||||
if (HasColormap) {
|
|
||||||
ColorMapSize = 2 << (ch & 7);
|
|
||||||
} else {
|
} else {
|
||||||
ColorMapSize = 0;
|
load_gif_(rdr, anim);
|
||||||
}
|
}
|
||||||
// int OriginalResolution = ((ch>>4)&7)+1;
|
}
|
||||||
// int SortedTable = (ch&8)!=0;
|
|
||||||
ch = rdr.read_byte(); // Background Color index
|
|
||||||
ch = rdr.read_byte(); // Aspect ratio is N/64
|
|
||||||
CHECK_ERROR
|
|
||||||
|
|
||||||
// Read in global colormap:
|
Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data, const size_t length, bool anim) :
|
||||||
uchar transparent_pixel = 0;
|
Fl_Pixmap((char *const*)0)
|
||||||
char has_transparent = 0;
|
{
|
||||||
uchar Red[256], Green[256], Blue[256]; /* color map */
|
Fl_Image_Reader rdr;
|
||||||
if (HasColormap) {
|
if (rdr.open(imagename, data, length) == -1) {
|
||||||
for (int i=0; i < ColorMapSize; i++) {
|
ld(ERR_FILE_ACCESS);
|
||||||
Red[i] = rdr.read_byte();
|
} else {
|
||||||
Green[i] = rdr.read_byte();
|
load_gif_(rdr, anim);
|
||||||
Blue[i] = rdr.read_byte();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CHECK_ERROR
|
}
|
||||||
|
|
||||||
int CodeSize; /* Code size, init from GIF header, increases... */
|
/**
|
||||||
char Interlace;
|
The default constructor creates an empty GIF image.
|
||||||
|
|
||||||
// Main parser loop: parse "blocks" until an image is found or error
|
*/
|
||||||
|
Fl_GIF_Image::Fl_GIF_Image() :
|
||||||
|
Fl_Pixmap((char *const*)0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
|
|
||||||
int i = rdr.read_byte();
|
/*
|
||||||
CHECK_ERROR
|
Internally used method to read from the LZW compressed data
|
||||||
int blocklen;
|
stream 'rdr' and decode it to 'Image' buffer.
|
||||||
|
|
||||||
if (i == 0x21) { // a "gif extension"
|
NOTE: This methode has been extracted from load_gif_()
|
||||||
ch = rdr.read_byte(); // extension type
|
in order to make the code more read/hand-able.
|
||||||
blocklen = rdr.read_byte();
|
|
||||||
CHECK_ERROR
|
|
||||||
|
|
||||||
if (ch == 0xF9 && blocklen == 4) { // Graphic Control Extension
|
|
||||||
// printf("Graphic Control Extension at offset %ld\n", rdr.tell()-2);
|
|
||||||
char bits = rdr.read_byte(); // Packed Fields
|
|
||||||
rdr.read_word(); // Delay Time
|
|
||||||
transparent_pixel = rdr.read_byte(); // Transparent Color Index
|
|
||||||
blocklen = rdr.read_byte(); // Block Terminator (must be zero)
|
|
||||||
CHECK_ERROR
|
|
||||||
if (bits & 1) has_transparent = 1;
|
|
||||||
}
|
|
||||||
else if (ch == 0xFF) { // Application Extension
|
|
||||||
// printf("Application Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
|
||||||
; // skip data
|
|
||||||
}
|
|
||||||
else if (ch == 0xFE) { // Comment Extension
|
|
||||||
// printf("Comment Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
|
||||||
; // skip data
|
|
||||||
}
|
|
||||||
else if (ch == 0x01) { // Plain Text Extension
|
|
||||||
// printf("Plain Text Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
|
||||||
; // skip data
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Fl::warning("%s: unknown GIF extension 0x%02x at offset %ld, length = %d",
|
|
||||||
rdr.name(), ch, rdr.tell()-3, blocklen);
|
|
||||||
; // skip data
|
|
||||||
}
|
|
||||||
} else if (i == 0x2c) { // an image: Image Descriptor follows
|
|
||||||
// printf("Image Descriptor at offset %ld\n", rdr.tell());
|
|
||||||
rdr.read_word(); // Image Left Position
|
|
||||||
rdr.read_word(); // Image Top Position
|
|
||||||
Width = rdr.read_word(); // Image Width
|
|
||||||
Height = rdr.read_word(); // Image Height
|
|
||||||
ch = rdr.read_byte(); // Packed Fields
|
|
||||||
CHECK_ERROR
|
|
||||||
Interlace = ((ch & 0x40) != 0);
|
|
||||||
if (ch & 0x80) { // image has local color table
|
|
||||||
// printf("Local Color Table at offset %ld\n", rdr.tell());
|
|
||||||
BitsPerPixel = (ch & 7) + 1;
|
|
||||||
ColorMapSize = 2 << (ch & 7);
|
|
||||||
for (i=0; i < ColorMapSize; i++) {
|
|
||||||
Red[i] = rdr.read_byte();
|
|
||||||
Green[i] = rdr.read_byte();
|
|
||||||
Blue[i] = rdr.read_byte();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CHECK_ERROR
|
|
||||||
break; // okay, this is the image we want
|
|
||||||
} else if (i == 0x3b) { // Trailer (end of GIF data)
|
|
||||||
// printf("Trailer found at offset %ld\n", rdr.tell());
|
|
||||||
Fl::error("%s: no image data found.", rdr.name());
|
|
||||||
ld(ERR_NO_IMAGE); // this GIF file is "empty" (no image)
|
|
||||||
return; // terminate
|
|
||||||
} else {
|
|
||||||
Fl::error("%s: unknown GIF code 0x%02x at offset %ld", rdr.name(), i, rdr.tell()-1);
|
|
||||||
ld(ERR_FORMAT); // broken file
|
|
||||||
return; // terminate
|
|
||||||
}
|
|
||||||
CHECK_ERROR
|
|
||||||
|
|
||||||
// skip all data (sub)blocks:
|
|
||||||
while (blocklen > 0) {
|
|
||||||
rdr.skip(blocklen);
|
|
||||||
blocklen = rdr.read_byte();
|
|
||||||
}
|
|
||||||
// printf("End of data (sub)blocks at offset %ld\n", rdr.tell());
|
|
||||||
}
|
|
||||||
|
|
||||||
// read image data
|
|
||||||
|
|
||||||
// printf("Image Data at offset %ld\n", rdr.tell());
|
|
||||||
|
|
||||||
CodeSize = rdr.read_byte() + 1; // LZW Minimum Code Size
|
|
||||||
CHECK_ERROR
|
|
||||||
|
|
||||||
if (BitsPerPixel >= CodeSize) { // Workaround for broken GIF files...
|
|
||||||
BitsPerPixel = CodeSize - 1;
|
|
||||||
ColorMapSize = 1 << BitsPerPixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix images w/o color table. The standard allows this and lets the
|
|
||||||
// decoder choose a default color table. The standard recommends the
|
|
||||||
// first two color table entries should be black and white.
|
|
||||||
|
|
||||||
if (ColorMapSize == 0) { // no global and no local color table
|
|
||||||
Fl::warning("%s does not have a color table, using default.\n", rdr.name());
|
|
||||||
BitsPerPixel = CodeSize - 1;
|
|
||||||
ColorMapSize = 1 << BitsPerPixel;
|
|
||||||
Red[0] = Green[0] = Blue[0] = 0; // black
|
|
||||||
Red[1] = Green[1] = Blue[1] = 255; // white
|
|
||||||
for (int i = 2; i < ColorMapSize; i++) {
|
|
||||||
Red[i] = Green[i] = Blue[i] = (uchar)(255 * i / (ColorMapSize - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix transparent pixel index outside ColorMap (Issue #271)
|
|
||||||
if (has_transparent && transparent_pixel >= ColorMapSize) {
|
|
||||||
for (int k = ColorMapSize; k <= transparent_pixel; k++)
|
|
||||||
Red[k] = Green[k] = Blue[k] = 0xff; // white (color is irrelevant)
|
|
||||||
ColorMapSize = transparent_pixel + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (0) // TEST/DEBUG: fill color table to maximum size
|
|
||||||
for (int i = ColorMapSize; i < 256; i++) {
|
|
||||||
Red[i] = Green[i] = Blue[i] = 0; // black
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CHECK_ERROR
|
|
||||||
|
|
||||||
// now read the LZW compressed image data
|
|
||||||
|
|
||||||
Image = new uchar[Width*Height];
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
void Fl_GIF_Image::lzw_decode(Fl_Image_Reader &rdr, uchar *Image,
|
||||||
|
int Width, int Height, int CodeSize, int ColorMapSize, int Interlace) {
|
||||||
int YC = 0, Pass = 0; /* Used to de-interlace the picture */
|
int YC = 0, Pass = 0; /* Used to de-interlace the picture */
|
||||||
uchar *p = Image;
|
uchar *p = Image;
|
||||||
uchar *eol = p+Width;
|
uchar *eol = p+Width;
|
||||||
|
@ -419,10 +285,10 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
/* Fetch the next code from the raster data stream. The codes can be
|
/* Fetch the next code from the raster data stream. The codes can be
|
||||||
* any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
|
* any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
|
||||||
* maintain our location as a pointer and a bit offset.
|
* maintain our location as a pointer and a bit offset.
|
||||||
* In addition, GIF adds totally useless and annoying block counts
|
* In addition, GIF adds totally useless and annoying block counts
|
||||||
* that must be correctly skipped over. */
|
* that must be correctly skipped over. */
|
||||||
int CurCode = thisbyte;
|
int CurCode = thisbyte;
|
||||||
if (frombit+CodeSize > 7) {
|
if (frombit+CodeSize > 7) {
|
||||||
if (blocklen <= 0) {
|
if (blocklen <= 0) {
|
||||||
|
@ -455,8 +321,11 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurCode == EOFCode)
|
if (CurCode == EOFCode) {
|
||||||
|
rdr.skip(blocklen);
|
||||||
|
blocklen = rdr.read_byte(); // Block-Terminator must follow!
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
uchar OutCode[4097]; // temporary array for reversing codes
|
uchar OutCode[4097]; // temporary array for reversing codes
|
||||||
uchar *tp = OutCode;
|
uchar *tp = OutCode;
|
||||||
|
@ -515,47 +384,52 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||||
}
|
}
|
||||||
OldCode = CurCode;
|
OldCode = CurCode;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We are done reading the image, now convert to xpm
|
|
||||||
|
|
||||||
w(Width);
|
/*
|
||||||
h(Height);
|
Internally used function to convert raw 'Image' data
|
||||||
d(1);
|
to XPM format in an allocated buffer 'new_data'.
|
||||||
|
|
||||||
|
NOTE: This function has been extracted from load_gif_()
|
||||||
|
in order to make the code more read/hand-able.
|
||||||
|
|
||||||
|
*/
|
||||||
|
static char ** convert_to_xpm(uchar *Image, int Width, int Height, ColorMap &CMap, int ColorMapSize, int transparent_pixel) {
|
||||||
// allocate line pointer arrays:
|
// allocate line pointer arrays:
|
||||||
new_data = new char*[Height+2];
|
char **new_data = new char*[Height+2];
|
||||||
|
|
||||||
// transparent pixel must be zero, swap if it isn't:
|
// transparent pixel must be zero, swap if it isn't:
|
||||||
if (has_transparent && transparent_pixel != 0) {
|
if (transparent_pixel > 0) {
|
||||||
// swap transparent pixel with zero
|
// swap transparent pixel with zero
|
||||||
p = Image+Width*Height;
|
uchar *p = Image+Width*Height;
|
||||||
while (p-- > Image) {
|
while (p-- > Image) {
|
||||||
if (*p==transparent_pixel) *p = 0;
|
if (*p==transparent_pixel) *p = 0;
|
||||||
else if (!*p) *p = transparent_pixel;
|
else if (!*p) *p = transparent_pixel;
|
||||||
}
|
}
|
||||||
uchar t;
|
uchar t;
|
||||||
t = Red[0];
|
t = CMap.Red[0];
|
||||||
Red[0] = Red[transparent_pixel];
|
CMap.Red[0] = CMap.Red[transparent_pixel];
|
||||||
Red[transparent_pixel] = t;
|
CMap.Red[transparent_pixel] = t;
|
||||||
|
|
||||||
t = Green[0];
|
t = CMap.Green[0];
|
||||||
Green[0] = Green[transparent_pixel];
|
CMap.Green[0] = CMap.Green[transparent_pixel];
|
||||||
Green[transparent_pixel] = t;
|
CMap.Green[transparent_pixel] = t;
|
||||||
|
|
||||||
t = Blue[0];
|
t = CMap.Blue[0];
|
||||||
Blue[0] = Blue[transparent_pixel];
|
CMap.Blue[0] = CMap.Blue[transparent_pixel];
|
||||||
Blue[transparent_pixel] = t;
|
CMap.Blue[transparent_pixel] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find out what colors are actually used:
|
// find out what colors are actually used:
|
||||||
uchar used[256]; uchar remap[256];
|
uchar used[256]; uchar remap[256];
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < ColorMapSize; i++) used[i] = 0;
|
for (i = 0; i < ColorMapSize; i++) used[i] = 0;
|
||||||
p = Image+Width*Height;
|
uchar *p = Image+Width*Height;
|
||||||
while (p-- > Image) used[*p] = 1;
|
while (p-- > Image) used[*p] = 1;
|
||||||
|
|
||||||
// remap them to start with printing characters:
|
// remap them to start with printing characters:
|
||||||
int base = has_transparent && used[0] ? ' ' : ' '+1;
|
int base = transparent_pixel >= 0 && used[0] ? ' ' : ' '+1;
|
||||||
int numcolors = 0;
|
int numcolors = 0;
|
||||||
for (i = 0; i < ColorMapSize; i++) if (used[i]) {
|
for (i = 0; i < ColorMapSize; i++) if (used[i]) {
|
||||||
remap[i] = (uchar)(base++);
|
remap[i] = (uchar)(base++);
|
||||||
|
@ -563,6 +437,7 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the first line of xpm data (use suffix as temp array):
|
// write the first line of xpm data (use suffix as temp array):
|
||||||
|
uchar Suffix[4096];
|
||||||
int length = snprintf((char*)(Suffix), sizeof(Suffix),
|
int length = snprintf((char*)(Suffix), sizeof(Suffix),
|
||||||
"%d %d %d %d",Width,Height,-numcolors,1);
|
"%d %d %d %d",Width,Height,-numcolors,1);
|
||||||
new_data[0] = new char[length+1];
|
new_data[0] = new char[length+1];
|
||||||
|
@ -572,9 +447,9 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||||
new_data[1] = (char*)(p = new uchar[4*numcolors]);
|
new_data[1] = (char*)(p = new uchar[4*numcolors]);
|
||||||
for (i = 0; i < ColorMapSize; i++) if (used[i]) {
|
for (i = 0; i < ColorMapSize; i++) if (used[i]) {
|
||||||
*p++ = remap[i];
|
*p++ = remap[i];
|
||||||
*p++ = Red[i];
|
*p++ = CMap.Red[i];
|
||||||
*p++ = Green[i];
|
*p++ = CMap.Green[i];
|
||||||
*p++ = Blue[i];
|
*p++ = CMap.Blue[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// remap the image data:
|
// remap the image data:
|
||||||
|
@ -588,9 +463,344 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||||
new_data[i + 2][Width] = 0;
|
new_data[i + 2][Width] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
data((const char **)new_data, Height + 2);
|
return new_data;
|
||||||
alloc_data = 1;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This method reads GIF image data and creates an RGB or RGBA image. The GIF
|
||||||
|
format supports only 1 bit for alpha. The final image data is stored in
|
||||||
|
a modified XPM format (Fl_GIF_Image is a subclass of Fl_Pixmap).
|
||||||
|
To avoid code duplication, we use an Fl_Image_Reader that reads data from
|
||||||
|
either a file or from memory.
|
||||||
|
|
||||||
|
wcout 2022/01/20 - Added animated GIF support:
|
||||||
|
If the load_gif_() method is called with 'anim=true', then not only the first
|
||||||
|
image is decoded (as with Fl_GIF_Image), but all contained images are read.
|
||||||
|
The new Fl_Anim_GIF_Image class is derived from Fl_GIF_Image and utilises this
|
||||||
|
feature in order to avoid code duplication of the GIF decoding routines.
|
||||||
|
The first image is in this case (additionally) stored in the usual way as described
|
||||||
|
above (making the Fl_Anim_GIF_Image a normal Fl_GIF_Image too).
|
||||||
|
All subsequent images are only decoded (and not converted to XPM) and passed
|
||||||
|
to Fl_Anim_GIF_Image, which stores them on its own (in RGBA format).
|
||||||
|
*/
|
||||||
|
void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr, bool anim/*=false*/)
|
||||||
|
{
|
||||||
|
uchar *Image = 0L; // internal temporary image data array
|
||||||
|
int frame = 0;
|
||||||
|
|
||||||
|
// Needed for proper decoding of *all* images in file (Fl_Anim_GIF_Image)
|
||||||
|
uchar background_color_index = 0;
|
||||||
|
GIF_FRAME::CPAL GlobalColorTable[256];
|
||||||
|
bool HasGlobalColorTable = false;
|
||||||
|
GIF_FRAME::CPAL LocalColorTable[256];
|
||||||
|
bool HasLocalColorTable = false;
|
||||||
|
|
||||||
|
w(0); h(0);
|
||||||
|
|
||||||
|
// printf("\nFl_GIF_Image::load_gif_ : %s\n", rdr.name());
|
||||||
|
|
||||||
|
{char b[6] = { 0 };
|
||||||
|
for (int i=0; i<6; ++i) b[i] = rdr.read_byte();
|
||||||
|
if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
|
||||||
|
Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", rdr.name());
|
||||||
|
ld(ERR_FORMAT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
|
||||||
|
Fl::warning("%s is version %c%c%c.",rdr.name(),b[3],b[4],b[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScreenWidth = rdr.read_word();
|
||||||
|
int ScreenHeight = rdr.read_word();
|
||||||
|
int Width = ScreenWidth;
|
||||||
|
int Height = ScreenHeight;
|
||||||
|
|
||||||
|
uchar ch = rdr.read_byte();
|
||||||
|
CHECK_ERROR
|
||||||
|
char HasColormap = ((ch & 0x80) != 0);
|
||||||
|
HasGlobalColorTable = HasColormap;
|
||||||
|
memset(GlobalColorTable, 0, sizeof(GlobalColorTable));
|
||||||
|
int BitsPerPixel = (ch & 7) + 1;
|
||||||
|
int ColorMapSize = HasColormap ? 2 << (ch & 7) : 0;
|
||||||
|
// int OriginalResolution = ((ch>>4)&7)+1;
|
||||||
|
// int SortedTable = (ch&8)!=0;
|
||||||
|
background_color_index = rdr.read_byte(); // Background Color index
|
||||||
|
ch = rdr.read_byte(); // Aspect ratio is N/64
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
// Read in global colormap:
|
||||||
|
uchar transparent_pixel = 0;
|
||||||
|
char has_transparent = 0;
|
||||||
|
char user_input = 0;
|
||||||
|
int delay = 0;
|
||||||
|
int dispose = 0;
|
||||||
|
int XPos = 0;
|
||||||
|
int YPos = 0;
|
||||||
|
struct ColorMap CMap; /* color map */
|
||||||
|
if (HasColormap) {
|
||||||
|
for (int i=0; i < ColorMapSize; i++) {
|
||||||
|
CMap.Red[i] = rdr.read_byte();
|
||||||
|
CMap.Green[i] = rdr.read_byte();
|
||||||
|
CMap.Blue[i] = rdr.read_byte();
|
||||||
|
// store away for reading of further images in file (Fl_Anim_GIF_Image)
|
||||||
|
// because the values are changed during processing.
|
||||||
|
GlobalColorTable[i].r = CMap.Red[i];
|
||||||
|
GlobalColorTable[i].g = CMap.Green[i];
|
||||||
|
GlobalColorTable[i].b = CMap.Blue[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
char Interlace = 0;
|
||||||
|
|
||||||
|
// Main parser loop: parse "blocks" until an image is found or error
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
int i = rdr.read_byte();
|
||||||
|
CHECK_ERROR
|
||||||
|
int blocklen = 0;
|
||||||
|
|
||||||
|
if (i == 0x21) { // a "gif extension"
|
||||||
|
ch = rdr.read_byte(); // extension type
|
||||||
|
blocklen = rdr.read_byte();
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
if (ch == 0xF9 && blocklen == 4) { // Graphic Control Extension
|
||||||
|
// printf("Graphic Control Extension at offset %ld\n", rdr.tell()-2);
|
||||||
|
uchar bits = rdr.read_byte(); // Packed Fields xxxDDDUT
|
||||||
|
dispose = (bits >> 2) & 7;
|
||||||
|
delay = rdr.read_word(); // Delay Time
|
||||||
|
transparent_pixel = rdr.read_byte(); // Transparent Color Index
|
||||||
|
blocklen = rdr.read_byte(); // Block Terminator (must be zero)
|
||||||
|
CHECK_ERROR
|
||||||
|
has_transparent = (bits & 1) ? 1 : 0;
|
||||||
|
user_input = (bits & 2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
else if (ch == 0xFF) { // Application Extension
|
||||||
|
// printf("Application Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||||
|
uchar buf[512];
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
for (i=0; i<blocklen; i++) buf[i] = rdr.read_byte();
|
||||||
|
blocklen = rdr.read_byte(); // read next Data Sub-block too for NETSCAPE ext.
|
||||||
|
CHECK_ERROR
|
||||||
|
if (blocklen) {
|
||||||
|
while (blocklen--) buf[i++] = rdr.read_byte();
|
||||||
|
blocklen = rdr.read_byte();
|
||||||
|
}
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
// Notify derived class on loaded extension data
|
||||||
|
|
||||||
|
GIF_FRAME f(frame, buf);
|
||||||
|
on_extension_data(f);
|
||||||
|
}
|
||||||
|
else if (ch == 0xFE) { // Comment Extension
|
||||||
|
// printf("Comment Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||||
|
; // skip data
|
||||||
|
}
|
||||||
|
else if (ch == 0x01) { // Plain Text Extension
|
||||||
|
// printf("Plain Text Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||||
|
; // skip data
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Fl::warning("%s: unknown GIF extension 0x%02x at offset %ld, length = %d",
|
||||||
|
rdr.name(), ch, rdr.tell()-3, blocklen);
|
||||||
|
; // skip data
|
||||||
|
}
|
||||||
|
} else if (i == 0x2c) { // an image: Image Descriptor follows
|
||||||
|
// printf("Image Descriptor at offset %ld\n", rdr.tell());
|
||||||
|
XPos = rdr.read_word(); // Image Left Position
|
||||||
|
YPos = rdr.read_word(); // Image Top Position
|
||||||
|
Width = rdr.read_word(); // Image Width
|
||||||
|
Height = rdr.read_word(); // Image Height
|
||||||
|
ch = rdr.read_byte(); // Packed Fields
|
||||||
|
CHECK_ERROR
|
||||||
|
Interlace = ((ch & 0x40) != 0);
|
||||||
|
HasLocalColorTable = ch & 0x80;
|
||||||
|
if (ch & 0x80) { // image has local color table
|
||||||
|
// printf("Local Color Table at offset %ld\n", rdr.tell());
|
||||||
|
BitsPerPixel = (ch & 7) + 1;
|
||||||
|
ColorMapSize = 2 << (ch & 7);
|
||||||
|
memset(LocalColorTable, 0, sizeof(LocalColorTable));
|
||||||
|
for (i=0; i < ColorMapSize; i++) {
|
||||||
|
CMap.Red[i] = rdr.read_byte();
|
||||||
|
CMap.Green[i] = rdr.read_byte();
|
||||||
|
CMap.Blue[i] = rdr.read_byte();
|
||||||
|
// store away for reading of further images in file (Fl_Anim_GIF_Image)
|
||||||
|
// because the values are changed during processing.
|
||||||
|
LocalColorTable[i].r = CMap.Red[i];
|
||||||
|
LocalColorTable[i].g = CMap.Green[i];
|
||||||
|
LocalColorTable[i].b = CMap.Blue[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
// read image data
|
||||||
|
|
||||||
|
// printf("Image Data at offset %ld\n", rdr.tell());
|
||||||
|
|
||||||
|
int CodeSize = rdr.read_byte(); // LZW initial Code Size (increases...)
|
||||||
|
CHECK_ERROR
|
||||||
|
if (CodeSize < 2 || CodeSize > 8) { // though invalid, other decoders accept an use it
|
||||||
|
Fl::warning("Fl_GIF_Image: %s invalid LZW-initial code size %d.\n", rdr.name(), CodeSize);
|
||||||
|
}
|
||||||
|
CodeSize++;
|
||||||
|
|
||||||
|
// Fix images w/o color table. The standard allows this and lets the
|
||||||
|
// decoder choose a default color table. The standard recommends the
|
||||||
|
// first two color table entries should be black and white.
|
||||||
|
|
||||||
|
if (ColorMapSize == 0) { // no global and no local color table
|
||||||
|
Fl::warning("%s does not have a color table, using default.\n", rdr.name());
|
||||||
|
BitsPerPixel = CodeSize - 1;
|
||||||
|
ColorMapSize = 1 << BitsPerPixel;
|
||||||
|
CMap.Red[0] = CMap.Green[0] = CMap.Blue[0] = 0; // black
|
||||||
|
CMap.Red[1] = CMap.Green[1] = CMap.Blue[1] = 255; // white
|
||||||
|
for (int i = 2; i < ColorMapSize; i++) {
|
||||||
|
CMap.Red[i] = CMap.Green[i] = CMap.Blue[i] = (uchar)(255 * i / (ColorMapSize - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround for broken GIF files...
|
||||||
|
BitsPerPixel = CodeSize - 1;
|
||||||
|
if (1 << BitsPerPixel <= 256)
|
||||||
|
ColorMapSize = 1 << BitsPerPixel;
|
||||||
|
|
||||||
|
// Fix transparent pixel index outside ColorMap (Issue #271)
|
||||||
|
if (has_transparent && transparent_pixel >= ColorMapSize) {
|
||||||
|
for (int k = ColorMapSize; k <= transparent_pixel; k++)
|
||||||
|
CMap.Red[k] = CMap.Green[k] = CMap.Blue[k] = 0xff; // white (color is irrelevant)
|
||||||
|
ColorMapSize = transparent_pixel + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (0) // TEST/DEBUG: fill color table to maximum size
|
||||||
|
for (int i = ColorMapSize; i < 256; i++) {
|
||||||
|
CMap.Red[i] = CMap.Green[i] = CMap.Blue[i] = 0; // black
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
// now read the LZW compressed image data
|
||||||
|
|
||||||
|
Image = new uchar[Width*Height];
|
||||||
|
lzw_decode(rdr, Image, Width, Height, CodeSize, ColorMapSize, Interlace);
|
||||||
|
if (ld()) return; // CHECK_ERROR aborted already
|
||||||
|
|
||||||
|
// Notify derived class on loaded image data
|
||||||
|
|
||||||
|
GIF_FRAME gf(frame, ScreenWidth, ScreenHeight, XPos, YPos, Width, Height, Image);
|
||||||
|
gf.disposal(dispose, user_input ? -delay - 1 : delay);
|
||||||
|
gf.colors(ColorMapSize, background_color_index, has_transparent ? transparent_pixel : -1);
|
||||||
|
GIF_FRAME::CPAL cpal[256] = { { 0 } };
|
||||||
|
if (HasLocalColorTable)
|
||||||
|
gf.cpal = LocalColorTable;
|
||||||
|
else if (HasGlobalColorTable)
|
||||||
|
gf.cpal = GlobalColorTable;
|
||||||
|
else {
|
||||||
|
for (i=0; i < ColorMapSize; i++) {
|
||||||
|
cpal[i].r = CMap.Red[i]; cpal[i].g = CMap.Green[i]; cpal[i].b = CMap.Blue[i];
|
||||||
|
}
|
||||||
|
gf.cpal = cpal;
|
||||||
|
}
|
||||||
|
#if (0) // TEST/DEBUG: output palette values
|
||||||
|
printf("palette:\n");
|
||||||
|
for (i=0; i<ColorMapSize; i++) {
|
||||||
|
printf("%d: #%02X%02X%02X\n", i, gf.cpal[i].r, gf.cpal[i].g, gf.cpal[i].b);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
on_frame_data(gf);
|
||||||
|
|
||||||
|
// We are done reading the image, now convert to xpm (first image only)
|
||||||
|
if (!frame) {
|
||||||
|
if (anim && ( (Width != ScreenWidth) || (Height != ScreenHeight) )) {
|
||||||
|
// if we are reading this for Fl_Anim_GIF_Image, we must apply offsets
|
||||||
|
w(ScreenWidth);
|
||||||
|
h(ScreenHeight);
|
||||||
|
d(1);
|
||||||
|
uchar *moved_image = new uchar[ScreenWidth*ScreenHeight];
|
||||||
|
memset(moved_image, has_transparent ? transparent_pixel : 0, ScreenWidth*ScreenHeight);
|
||||||
|
int xstart = XPos; if (xstart < 0) xstart = 0;
|
||||||
|
int ystart = YPos; if (ystart < 0) ystart = 0;
|
||||||
|
int xmax = XPos + Width; if (xmax > ScreenWidth) xmax = ScreenWidth;
|
||||||
|
int ymax = YPos + Height; if (ymax > ScreenHeight) ymax = ScreenHeight;
|
||||||
|
for (int y = ystart; y<ymax; y++) {
|
||||||
|
uchar *src = Image + (y-YPos) * Width + (xstart-XPos);
|
||||||
|
uchar *dst = moved_image + y*ScreenWidth + xstart;
|
||||||
|
memcpy(dst, src, xmax-xstart);
|
||||||
|
}
|
||||||
|
char **new_data = convert_to_xpm(moved_image, ScreenWidth, ScreenHeight, CMap, ColorMapSize, has_transparent ? transparent_pixel : -1);
|
||||||
|
data((const char **)new_data, Height + 2);
|
||||||
|
alloc_data = 1;
|
||||||
|
delete[] moved_image;
|
||||||
|
} else {
|
||||||
|
// Fl_GIF_Image does not apply offsets and just show the first frame at 0, 0
|
||||||
|
w(Width);
|
||||||
|
h(Height);
|
||||||
|
d(1);
|
||||||
|
char **new_data = convert_to_xpm(Image, Width, Height, CMap, ColorMapSize, has_transparent ? transparent_pixel : -1);
|
||||||
|
data((const char **)new_data, Height + 2);
|
||||||
|
alloc_data = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] Image;
|
||||||
|
Image = NULL;
|
||||||
|
|
||||||
|
if (!anim)
|
||||||
|
break; // okay, it is only the first image we want
|
||||||
|
frame++; // continue to read more images (of animated GIF)
|
||||||
|
// end of Image Descriptor block processing
|
||||||
|
} else if (i == 0x3b) { // Trailer (end of GIF data)
|
||||||
|
// printf("Trailer found at offset %ld\n", rdr.tell());
|
||||||
|
if (!frame) {
|
||||||
|
Fl::error("%s: no image data found.", rdr.name());
|
||||||
|
ld(ERR_NO_IMAGE); // this GIF file is "empty" (no image)
|
||||||
|
}
|
||||||
|
return; // terminate
|
||||||
|
} else {
|
||||||
|
Fl::error("%s: unknown GIF code 0x%02x at offset %ld", rdr.name(), i, rdr.tell()-1);
|
||||||
|
ld(ERR_FORMAT); // broken file
|
||||||
|
return; // terminate
|
||||||
|
}
|
||||||
|
CHECK_ERROR
|
||||||
|
|
||||||
|
// skip all data (sub)blocks:
|
||||||
|
while (blocklen > 0) {
|
||||||
|
rdr.skip(blocklen);
|
||||||
|
blocklen = rdr.read_byte();
|
||||||
|
}
|
||||||
|
// printf("End of data (sub)blocks at offset %ld\n", rdr.tell());
|
||||||
|
}
|
||||||
|
|
||||||
delete[] Image;
|
|
||||||
|
|
||||||
} // load_gif_()
|
} // load_gif_()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The protected load() methods are used by Fl_Anim_GIF_Image
|
||||||
|
to request loading of animated GIF's.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void Fl_GIF_Image::load(const char* filename, bool anim)
|
||||||
|
{
|
||||||
|
Fl_Image_Reader rdr;
|
||||||
|
if (rdr.open(filename) == -1) {
|
||||||
|
Fl::error("Fl_GIF_Image: Unable to open %s!", filename);
|
||||||
|
ld(ERR_FILE_ACCESS);
|
||||||
|
} else {
|
||||||
|
load_gif_(rdr, anim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl_GIF_Image::load(const char *imagename, const unsigned char *data, const size_t len, bool anim)
|
||||||
|
{
|
||||||
|
Fl_Image_Reader rdr;
|
||||||
|
if (rdr.open(imagename, data, len) == -1) {
|
||||||
|
ld(ERR_FILE_ACCESS);
|
||||||
|
} else {
|
||||||
|
load_gif_(rdr, anim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -230,6 +230,7 @@ IMGCPPFILES = \
|
||||||
Fl_BMP_Image.cxx \
|
Fl_BMP_Image.cxx \
|
||||||
Fl_File_Icon2.cxx \
|
Fl_File_Icon2.cxx \
|
||||||
Fl_GIF_Image.cxx \
|
Fl_GIF_Image.cxx \
|
||||||
|
Fl_Anim_GIF_Image.cxx \
|
||||||
Fl_Help_Dialog.cxx \
|
Fl_Help_Dialog.cxx \
|
||||||
Fl_ICO_Image.cxx \
|
Fl_ICO_Image.cxx \
|
||||||
Fl_JPEG_Image.cxx \
|
Fl_JPEG_Image.cxx \
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <FL/Fl_Shared_Image.H>
|
#include <FL/Fl_Shared_Image.H>
|
||||||
#include <FL/Fl_BMP_Image.H>
|
#include <FL/Fl_BMP_Image.H>
|
||||||
#include <FL/Fl_GIF_Image.H>
|
#include <FL/Fl_GIF_Image.H>
|
||||||
|
#include <FL/Fl_Anim_GIF_Image.H>
|
||||||
#include <FL/Fl_JPEG_Image.H>
|
#include <FL/Fl_JPEG_Image.H>
|
||||||
#include <FL/Fl_PNG_Image.H>
|
#include <FL/Fl_PNG_Image.H>
|
||||||
#include <FL/Fl_PNM_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 ||
|
if (memcmp(header, "GIF87a", 6) == 0 ||
|
||||||
memcmp(header, "GIF89a", 6) == 0) // GIF file
|
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
|
// BMP
|
||||||
|
|
||||||
|
|
|
@ -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_Screen_Driver.H
|
||||||
Fl_get_system_colors.o: Fl_System_Driver.H
|
Fl_get_system_colors.o: Fl_System_Driver.H
|
||||||
Fl_get_system_colors.o: tile.xpm
|
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: ../config.h
|
||||||
Fl_GIF_Image.o: ../FL/Enumerations.H
|
Fl_GIF_Image.o: ../FL/Enumerations.H
|
||||||
Fl_GIF_Image.o: ../FL/Fl.H
|
Fl_GIF_Image.o: ../FL/Fl.H
|
||||||
|
|
|
@ -113,7 +113,7 @@ CREATE_EXAMPLE (navigation navigation.cxx fltk)
|
||||||
CREATE_EXAMPLE (output output.cxx fltk)
|
CREATE_EXAMPLE (output output.cxx fltk)
|
||||||
CREATE_EXAMPLE (overlay overlay.cxx fltk)
|
CREATE_EXAMPLE (overlay overlay.cxx fltk)
|
||||||
CREATE_EXAMPLE (pack pack.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 (pixmap_browser pixmap_browser.cxx "fltk_images;fltk")
|
||||||
CREATE_EXAMPLE (preferences preferences.fl fltk)
|
CREATE_EXAMPLE (preferences preferences.fl fltk)
|
||||||
CREATE_EXAMPLE (offscreen offscreen.cxx fltk)
|
CREATE_EXAMPLE (offscreen offscreen.cxx fltk)
|
||||||
|
|
|
@ -512,7 +512,10 @@ overlay$(EXEEXT): overlay.o
|
||||||
|
|
||||||
pack$(EXEEXT): pack.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)
|
pixmap_browser$(EXEEXT): pixmap_browser.o $(IMGLIBNAME)
|
||||||
echo Linking $@...
|
echo Linking $@...
|
||||||
|
|
|
@ -24,9 +24,18 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <FL/Fl_Help_Dialog.H>
|
#include <FL/Fl_Help_Dialog.H>
|
||||||
|
#include <FL/Fl_GIF_Image.H>
|
||||||
#include <FL/filename.H> /* FL_PATH_MAX */
|
#include <FL/filename.H> /* FL_PATH_MAX */
|
||||||
|
#include <FL/Fl.H> /* Fl::first_window(), etc */
|
||||||
#include <string.h> /* strcpy(), 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...
|
// 'main()' - Display the help GUI...
|
||||||
//
|
//
|
||||||
|
@ -35,6 +44,7 @@ int // O - Exit status
|
||||||
main(int argc, // I - Number of command-line arguments
|
main(int argc, // I - Number of command-line arguments
|
||||||
char *argv[]) // I - 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;
|
Fl_Help_Dialog *help = new Fl_Help_Dialog;
|
||||||
int i;
|
int i;
|
||||||
if (!Fl::args(argc, argv, i)) Fl::fatal(Fl::help);
|
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);
|
help->show(1, argv);
|
||||||
|
|
||||||
|
Fl::add_timeout(1./10, cb_refresh, help); // to animate GIF's
|
||||||
Fl::run();
|
Fl::run();
|
||||||
|
|
||||||
delete help;
|
delete help;
|
||||||
|
|
|
@ -263,6 +263,9 @@ Nested OL/UL:
|
||||||
</TR><TR>
|
</TR><TR>
|
||||||
<TD><IMG SRC="images/tiny.png" alt="Tiny FLTK logo"></TD>
|
<TD><IMG SRC="images/tiny.png" alt="Tiny FLTK logo"></TD>
|
||||||
<TD>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>
|
</TR><TR>
|
||||||
<TD><IMG SRC="images/Fl_Value_Input.png" alt="Fl_Value_Input"></TD>
|
<TD><IMG SRC="images/Fl_Value_Input.png" alt="Fl_Value_Input"></TD>
|
||||||
<TD>This is an image of Fl_Value_Input</TD>
|
<TD>This is an image of Fl_Value_Input</TD>
|
||||||
|
|
|
@ -18,17 +18,20 @@
|
||||||
#include <FL/Fl_Double_Window.H>
|
#include <FL/Fl_Double_Window.H>
|
||||||
#include <FL/Fl_Button.H>
|
#include <FL/Fl_Button.H>
|
||||||
#include <FL/Fl_Pixmap.H>
|
#include <FL/Fl_Pixmap.H>
|
||||||
|
#include <FL/Fl_Anim_GIF_Image.H>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "pixmaps/porsche.xpm"
|
#include "pixmaps/animated_fluid_gif.h"
|
||||||
|
|
||||||
#include <FL/Fl_Toggle_Button.H>
|
#include <FL/Fl_Toggle_Button.H>
|
||||||
|
|
||||||
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb;
|
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb;
|
||||||
Fl_Button *b;
|
Fl_Button *b;
|
||||||
Fl_Double_Window *w;
|
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;
|
int i = 0;
|
||||||
if (leftb->value()) i |= FL_ALIGN_LEFT;
|
if (leftb->value()) i |= FL_ALIGN_LEFT;
|
||||||
if (rightb->value()) i |= FL_ALIGN_RIGHT;
|
if (rightb->value()) i |= FL_ALIGN_RIGHT;
|
||||||
|
@ -42,6 +45,21 @@ void button_cb(Fl_Widget *,void *) {
|
||||||
w->redraw();
|
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 dvisual = 0;
|
||||||
int arg(int, char **argv, int &i) {
|
int arg(int, char **argv, int &i) {
|
||||||
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
|
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 main(int argc, char **argv) {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
if (Fl::args(argc,argv,i,arg) < argc)
|
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_Double_Window window(400,440); ::w = &window;
|
||||||
Fl_Button b(140,160,120,120,"Pixmap"); ::b = &b;
|
Fl_Button b(130,170,140,140,"Pixmap"); ::b = &b;
|
||||||
Fl_Pixmap *pixmap = new Fl_Pixmap(porsche_xpm);
|
|
||||||
Fl_Pixmap *depixmap;
|
Fl_Anim_GIF_Image::animate = true;
|
||||||
depixmap = (Fl_Pixmap *)pixmap->copy();
|
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();
|
depixmap->inactive();
|
||||||
|
b.deimage(depixmap);
|
||||||
|
|
||||||
// "bind" images to avoid memory leak reports (valgrind, asan)
|
// "bind" images to avoid memory leak reports (valgrind, asan)
|
||||||
// note: these reports are benign because they appear at exit, but anyway
|
// note: these reports are benign because they appear at exit, but anyway
|
||||||
|
|
||||||
b.bind_image(pixmap);
|
b.bind_image(pixmap);
|
||||||
b.bind_deimage(depixmap);
|
b.bind_deimage(depixmap);
|
||||||
|
|
||||||
|
@ -82,7 +106,17 @@ int main(int argc, char **argv) {
|
||||||
overb->callback(button_cb);
|
overb->callback(button_cb);
|
||||||
inactb = new Fl_Toggle_Button(125,75,100,25,"inactive");
|
inactb = new Fl_Toggle_Button(125,75,100,25,"inactive");
|
||||||
inactb->callback(button_cb);
|
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.resizable(window);
|
||||||
window.end();
|
window.end();
|
||||||
window.show(argc,argv);
|
window.show(argc,argv);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <FL/Fl_Double_Window.H>
|
#include <FL/Fl_Double_Window.H>
|
||||||
#include <FL/Fl_Button.H>
|
#include <FL/Fl_Button.H>
|
||||||
#include <FL/Fl_Shared_Image.H>
|
#include <FL/Fl_Shared_Image.H>
|
||||||
|
#include <FL/Fl_GIF_Image.H>
|
||||||
#include <FL/Fl_Printer.H>
|
#include <FL/Fl_Printer.H>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -36,6 +37,17 @@ Fl_Shared_Image *img;
|
||||||
|
|
||||||
static char name[1024];
|
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) {
|
void load_file(const char *n) {
|
||||||
if (img) {
|
if (img) {
|
||||||
((Fl_Shared_Image*)b->image())->release();
|
((Fl_Shared_Image*)b->image())->release();
|
||||||
|
@ -118,8 +130,10 @@ void svg_cb(Fl_Widget *widget, void *) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int dvisual = 0;
|
int dvisual = 0;
|
||||||
|
int animate = 1;
|
||||||
int arg(int, char **argv, int &i) {
|
int arg(int, char **argv, int &i) {
|
||||||
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
|
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
|
||||||
|
if (argv[i][1] == 'a') {animate = 1; i++; return 1;}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +145,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
Fl::args(argc,argv,i,arg);
|
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_Double_Window window(400,450); ::w = &window;
|
||||||
Fl_Box b(10,45,380,380); ::b = &b;
|
Fl_Box b(10,45,380,380); ::b = &b;
|
||||||
b.box(FL_THIN_DOWN_BOX);
|
b.box(FL_THIN_DOWN_BOX);
|
||||||
|
@ -146,5 +163,7 @@ int main(int argc, char **argv) {
|
||||||
svg.callback(svg_cb);
|
svg.callback(svg_cb);
|
||||||
|
|
||||||
window.show(argc,argv);
|
window.show(argc,argv);
|
||||||
|
if (animate)
|
||||||
|
Fl::add_timeout(1./10, cb_forced_redraw); // force periodic redraw
|
||||||
return Fl::run();
|
return Fl::run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 |
|
@ -47,11 +47,10 @@ int arg(int argc, char **argv, int &i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
#ifdef FLTK_USE_X11
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
Fl::args(argc,argv,i,arg);
|
Fl::args(argc,argv,i,arg);
|
||||||
|
|
||||||
|
#ifdef FLTK_USE_X11
|
||||||
if (visid >= 0) {
|
if (visid >= 0) {
|
||||||
fl_open_display();
|
fl_open_display();
|
||||||
XVisualInfo templt; int num;
|
XVisualInfo templt; int num;
|
||||||
|
|
|
@ -609,7 +609,7 @@ int main(int argc, char** argv)
|
||||||
end_list /= 16;
|
end_list /= 16;
|
||||||
}
|
}
|
||||||
argc = 1;
|
argc = 1;
|
||||||
for (long y = off; y < end_list; y++) {
|
for (int y = off; y < end_list; y++) {
|
||||||
int o = 0;
|
int o = 0;
|
||||||
char bu[25]; // index label
|
char bu[25]; // index label
|
||||||
char buf[16 * 6]; // utf8 text
|
char buf[16 * 6]; // utf8 text
|
||||||
|
@ -622,7 +622,7 @@ int main(int argc, char** argv)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
buf[o] = '\0';
|
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);
|
Fl_Input *b = new Fl_Input(200,(y-off)*25,80,25);
|
||||||
b->textfont(FL_COURIER);
|
b->textfont(FL_COURIER);
|
||||||
b->value(fl_strdup(bu));
|
b->value(fl_strdup(bu));
|
||||||
|
|
Loading…
Reference in New Issue