#include <FL/Fl.H>
#include <FL/platform.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Pixmap.H>
#include <stdio.h>
#include "flstring.h"
#include <ctype.h>
void Fl_Pixmap::measure() {
int W, H;
if (w()<0 && data()) {
fl_measure_pixmap(data(), W, H);
w(W); h(H);
cache_w_ = cache_h_ = 0;
}
}
void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
fl_graphics_driver->draw_pixmap(this, XP, YP, WP, HP, cx, cy);
}
Fl_Pixmap::~Fl_Pixmap() {
uncache();
delete_data();
}
void Fl_Pixmap::uncache() {
if (id_) {
Fl_Graphics_Driver::default_driver().uncache_pixmap(id_);
id_ = 0;
}
if (mask_) {
Fl_Graphics_Driver::default_driver().delete_bitmask(mask_);
mask_ = 0;
}
}
void Fl_Pixmap::label(Fl_Widget* widget) {
widget->image(this);
}
void Fl_Pixmap::label(Fl_Menu_Item* m) {
m->label(FL_IMAGE_LABEL, (const char*)this);
}
void Fl_Pixmap::copy_data() {
if (alloc_data) return;
char **new_data, **new_row; int i, ncolors, chars_per_pixel, chars_per_line;
sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
chars_per_line = chars_per_pixel * data_w() + 1;
if (ncolors < 0) new_data = new char *[data_h() + 2];
else new_data = new char *[data_h() + ncolors + 1];
new_data[0] = new char[strlen(data()[0]) + 1];
strcpy(new_data[0], data()[0]);
if (ncolors < 0) {
ncolors = -ncolors;
new_row = new_data + 1;
*new_row = new char[ncolors * 4];
memcpy(*new_row, data()[1], ncolors * 4);
ncolors = 1;
new_row ++;
} else {
for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) {
*new_row = new char[strlen(data()[i + 1]) + 1];
strcpy(*new_row, data()[i + 1]);
}
}
for (i = 0; i < data_h(); i ++, new_row ++) {
*new_row = new char[chars_per_line];
memcpy(*new_row, data()[i + ncolors + 1], chars_per_line);
}
data((const char **)new_data, data_h() + ncolors + 1);
alloc_data = 1;
}
Fl_Image *Fl_Pixmap::copy(int W, int H) const {
Fl_Pixmap *new_image; if (!data()) { return new Fl_Pixmap((char *const*)0);
}
if (W == data_w() && H == data_h()) {
new_image = new Fl_Pixmap(data());
new_image->copy_data();
return new_image;
}
if (W <= 0 || H <= 0) return 0;
char **new_data, **new_row, *new_ptr, new_info[255]; const char *old_ptr; int i, c, sy, dx, dy, xerr, yerr, xmod, ymod, xstep, ystep; int ncolors, chars_per_pixel, chars_per_line;
sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
chars_per_line = chars_per_pixel * W + 1;
snprintf(new_info, sizeof(new_info), "%d %d %d %d", W, H, ncolors, chars_per_pixel);
xmod = data_w() % W;
xstep = (data_w() / W) * chars_per_pixel;
ymod = data_h() % H;
ystep = data_h() / H;
if (ncolors < 0) new_data = new char *[H + 2];
else new_data = new char *[H + ncolors + 1];
new_data[0] = new char[strlen(new_info) + 1];
strcpy(new_data[0], new_info);
if (ncolors < 0) {
ncolors = -ncolors;
new_row = new_data + 1;
*new_row = new char[ncolors * 4];
memcpy(*new_row, data()[1], ncolors * 4);
ncolors = 1;
new_row ++;
} else {
for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) {
*new_row = new char[strlen(data()[i + 1]) + 1];
strcpy(*new_row, data()[i + 1]);
}
}
for (dy = H, sy = 0, yerr = H; dy > 0; dy --, new_row ++) {
*new_row = new char[chars_per_line];
new_ptr = *new_row;
for (dx = W, xerr = W, old_ptr = data()[sy + ncolors + 1];
dx > 0;
dx --) {
for (c = 0; c < chars_per_pixel; c ++) *new_ptr++ = old_ptr[c];
old_ptr += xstep;
xerr -= xmod;
if (xerr <= 0) {
xerr += W;
old_ptr += chars_per_pixel;
}
}
*new_ptr = '\0';
sy += ystep;
yerr -= ymod;
if (yerr <= 0) {
yerr += H;
sy ++;
}
}
new_image = new Fl_Pixmap((char*const*)new_data);
new_image->alloc_data = 1;
return new_image;
}
void Fl_Pixmap::color_average(Fl_Color c, float i) {
uncache();
copy_data();
uchar r, g, b;
unsigned ia, ir, ig, ib;
Fl::get_color(c, r, g, b);
if (i < 0.0f) i = 0.0f;
else if (i > 1.0f) i = 1.0f;
ia = (unsigned)(256 * i);
ir = r * (256 - ia);
ig = g * (256 - ia);
ib = b * (256 - ia);
char line[255]; int color, ncolors, chars_per_pixel;
sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
if (ncolors < 0) {
ncolors = -ncolors;
uchar *cmap = (uchar *)(data()[1]);
for (color = 0; color < ncolors; color ++, cmap += 4) {
cmap[1] = (ia * cmap[1] + ir) >> 8;
cmap[2] = (ia * cmap[2] + ig) >> 8;
cmap[3] = (ia * cmap[3] + ib) >> 8;
}
} else {
for (color = 0; color < ncolors; color ++) {
const char *p = data()[color + 1] + chars_per_pixel + 1;
const char *previous_word = p;
for (;;) {
while (*p && isspace(*p)) p++;
char what = *p++;
while (*p && !isspace(*p)) p++;
while (*p && isspace(*p)) p++;
if (!*p) {p = previous_word; break;}
if (what == 'c') break;
previous_word = p;
while (*p && !isspace(*p)) p++;
}
if (fl_parse_color(p, r, g, b)) {
r = (ia * r + ir) >> 8;
g = (ia * g + ig) >> 8;
b = (ia * b + ib) >> 8;
if (chars_per_pixel > 1) snprintf(line, sizeof(line),
"%c%c c #%02X%02X%02X",
data()[color + 1][0],
data()[color + 1][1], r, g, b);
else snprintf(line, sizeof(line), "%c c #%02X%02X%02X",
data()[color + 1][0], r, g, b);
delete[] (char *)data()[color + 1];
((char **)data())[color + 1] = new char[strlen(line) + 1];
strcpy((char *)data()[color + 1], line);
}
}
}
}
void Fl_Pixmap::delete_data() {
if (alloc_data) {
for (int i = 0; i < count(); i ++) delete[] (char *)data()[i];
delete[] (char **)data();
}
}
void Fl_Pixmap::set_data(const char * const * p) {
int height, ncolors;
if (p) {
sscanf(p[0],"%*d%d%d", &height, &ncolors);
if (ncolors < 0) data(p, height + 2);
else data(p, height + ncolors + 1);
}
}
void Fl_Pixmap::desaturate() {
uncache();
copy_data();
char line[255]; int i, ncolors, chars_per_pixel; uchar r, g, b;
sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel);
if (ncolors < 0) {
ncolors = -ncolors;
uchar *cmap = (uchar *)(data()[1]);
for (i = 0; i < ncolors; i ++, cmap += 4) {
g = (uchar)((cmap[1] * 31 + cmap[2] * 61 + cmap[3] * 8) / 100);
cmap[1] = cmap[2] = cmap[3] = g;
}
} else {
for (i = 0; i < ncolors; i ++) {
const char *p = data()[i + 1] + chars_per_pixel + 1;
const char *previous_word = p;
for (;;) {
while (*p && isspace(*p)) p++;
char what = *p++;
while (*p && !isspace(*p)) p++;
while (*p && isspace(*p)) p++;
if (!*p) {p = previous_word; break;}
if (what == 'c') break;
previous_word = p;
while (*p && !isspace(*p)) p++;
}
if (fl_parse_color(p, r, g, b)) {
g = (uchar)((r * 31 + g * 61 + b * 8) / 100);
if (chars_per_pixel > 1) {
snprintf(line, sizeof(line), "%c%c c #%02X%02X%02X",
data()[i + 1][0], data()[i + 1][1], g, g, g);
} else {
snprintf(line, sizeof(line), "%c c #%02X%02X%02X",
data()[i + 1][0], g, g, g);
}
delete[] (char *)data()[i + 1];
((char **)data())[i + 1] = new char[strlen(line) + 1];
strcpy((char *)data()[i + 1], line);
}
}
}
}