mirror of
https://github.com/NishiOwO/arena.git
synced 2025-04-22 01:04:41 +00:00
1800 lines
46 KiB
C
1800 lines
46 KiB
C
/* image.c - creates textured background and other pixmap stuff */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
|
|
#include "www.h"
|
|
#include "www.bm"
|
|
|
|
extern Display *display;
|
|
extern int screen;
|
|
extern Window win;
|
|
extern Visual *visual;
|
|
|
|
extern unsigned long labelColor, textColor, statusColor, strikeColor,
|
|
transparent, windowColor, windowBottomShadow, windowShadow;
|
|
|
|
extern int RPixelShift, GPixelShift, BPixelShift;
|
|
extern int RPixelMask, GPixelMask, BPixelMask;
|
|
extern int depth;
|
|
extern int IsIndex;
|
|
extern Doc *CurrentDoc;
|
|
extern Context *context;
|
|
extern BOOL OwnColorMap; /* howcome 10/8/95 */
|
|
|
|
extern int tileWidth, tileHeight;
|
|
extern unsigned char *tileData;
|
|
|
|
extern Pixmap default_pixmap;
|
|
extern int default_pixmap_width, default_pixmap_height;
|
|
extern Colormap colormap;
|
|
extern int Magic256[256];
|
|
extern int Magic16[256];
|
|
extern int Magic32[256];
|
|
extern int Magic64[256];
|
|
|
|
extern GC disp_gc;
|
|
extern unsigned int win_width, win_height;
|
|
extern int debug;
|
|
|
|
extern double Gamma;
|
|
|
|
extern HTAtom *text_atom;
|
|
extern HTAtom *html_atom;
|
|
extern HTAtom *html3_atom;
|
|
extern HTAtom *html_level3_atom;
|
|
extern HTAtom *gif_atom;
|
|
extern HTAtom *jpeg_atom;
|
|
extern HTAtom *png_atom;
|
|
extern HTAtom *png_exp_atom;
|
|
extern HTAtom *xpm_atom;
|
|
extern HTAtom *xbm_atom;
|
|
|
|
|
|
Pixmap smile, frown, note_pixmap, caution_pixmap, warning_pixmap;
|
|
int imaging; /* set to COLOR888, COLOR232, GREY4 or MONO */
|
|
Image *images; /* linked list of images */
|
|
Image *note_image, *caution_image, *warning_image; /* standard icons */
|
|
|
|
unsigned long stdcmap[128]; /* 2/3/2 color maps for gifs etc */
|
|
unsigned long greymap[16]; /* for mixing with unsaturated colors */
|
|
|
|
extern unsigned long mycmap[256];
|
|
|
|
Image *default_image = NULL;
|
|
|
|
|
|
#define smile_xbm_width 15
|
|
#define smile_xbm_height 15
|
|
|
|
/* janet 21/07/95: declared and defined but not used
|
|
static char smile_xbm_bits[] = {
|
|
0x1f, 0x7c, 0xe7, 0x73, 0xfb, 0x6f, 0xfd, 0x5f, 0xfd, 0x5f, 0xce, 0x39,
|
|
0xce, 0x39, 0xfe, 0x3f, 0xfe, 0x3f, 0xee, 0x3b, 0xdd, 0x5d, 0x3d, 0x5e,
|
|
0xfb, 0x6f, 0xe7, 0x73, 0x1f, 0x7c};
|
|
*/
|
|
|
|
#define frown_xbm_width 15
|
|
#define frown_xbm_height 15
|
|
|
|
/* janet 21/07/95: defined but not used
|
|
static char frown_xbm_bits[] = {
|
|
0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
|
|
0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
|
|
0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f};
|
|
*/
|
|
|
|
#define note_width 26
|
|
#define note_height 39
|
|
static char note_bits[] = {
|
|
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x38, 0xfc,
|
|
0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc,
|
|
0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc,
|
|
0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc,
|
|
0x30, 0xc6, 0x7c, 0xfc, 0x78, 0xef, 0x7d, 0xfc, 0x78, 0xef, 0x7f, 0xfc,
|
|
0x78, 0xef, 0x7f, 0xfc, 0x7c, 0x2f, 0x00, 0xfc, 0x7c, 0xcf, 0xff, 0xfc,
|
|
0x7c, 0xcf, 0xff, 0xfc, 0x7c, 0xcf, 0xff, 0xfc, 0x7c, 0x2f, 0xff, 0xfc,
|
|
0x7c, 0xef, 0xf8, 0xfc, 0x7c, 0xef, 0xfd, 0xfc, 0x38, 0xef, 0xfd, 0xfc,
|
|
0xc0, 0xf9, 0xff, 0xfc, 0xe0, 0xff, 0xff, 0xfc, 0xe0, 0xff, 0xff, 0xfc,
|
|
0xe0, 0xff, 0xff, 0xfc, 0xe0, 0xff, 0xff, 0xfc, 0xc0, 0xff, 0xff, 0xfc,
|
|
0x80, 0xff, 0x3f, 0xfc, 0x00, 0xff, 0x1f, 0xfc, 0x00, 0xff, 0x0f, 0xfc,
|
|
0x00, 0xff, 0x0f, 0xfc, 0x00, 0xff, 0x0f, 0xfc, 0x00, 0xff, 0x0f, 0xfc,
|
|
0x00, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc};
|
|
|
|
#define caution_width 26
|
|
#define caution_height 38
|
|
static char caution_bits[] = {
|
|
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 0xfc,
|
|
0x00, 0xe0, 0x01, 0xfc, 0x00, 0xee, 0x19, 0xfc, 0x00, 0xef, 0x3d, 0xfc,
|
|
0x00, 0xef, 0x3d, 0xfc, 0x00, 0xef, 0x3d, 0xfc, 0x00, 0xef, 0x3d, 0xfc,
|
|
0x70, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0x3d, 0xfc,
|
|
0x78, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0xdd, 0xfc,
|
|
0x78, 0xef, 0xed, 0xfc, 0x78, 0xff, 0xef, 0xfc, 0xf8, 0xff, 0xf7, 0xfc,
|
|
0xf8, 0xff, 0xf7, 0xfc, 0xf8, 0xff, 0xf7, 0xfc, 0xf8, 0xff, 0xf7, 0xfc,
|
|
0xf8, 0xff, 0xf9, 0xfc, 0xf8, 0x7f, 0xfe, 0xfc, 0xf8, 0xbf, 0xff, 0xfc,
|
|
0xf8, 0xbf, 0xff, 0xfc, 0xf8, 0xdf, 0xff, 0xfc, 0xf8, 0xdf, 0xff, 0xfc,
|
|
0xf8, 0xdf, 0xff, 0xfc, 0xf0, 0xff, 0x7f, 0xfc, 0xe0, 0xff, 0x3f, 0xfc,
|
|
0x80, 0xff, 0x0f, 0xfc, 0x80, 0xff, 0x07, 0xfc, 0x80, 0xff, 0x07, 0xfc,
|
|
0x80, 0xff, 0x07, 0xfc, 0x80, 0xff, 0x07, 0xfc, 0x80, 0xff, 0x07, 0xfc,
|
|
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc};
|
|
|
|
#define warning_width 26
|
|
#define warning_height 38
|
|
static char warning_bits[] = {
|
|
0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xfc,0x00,0xc0,0x00,0xfc,0x00,0xe0,0x01,
|
|
0xfc,0x00,0xee,0x19,0xfc,0x00,0xef,0x3d,0xfc,0x00,0xef,0x3d,0xfc,0x00,0xef,
|
|
0x3d,0xfc,0x00,0xef,0x3d,0xfc,0x70,0xef,0x3d,0xfc,0x78,0xef,0x3d,0xfc,0x78,
|
|
0x2f,0x30,0xfc,0x78,0x0f,0x38,0xfc,0x78,0x0f,0x3c,0xfc,0x78,0x07,0xde,0xfc,
|
|
0x78,0x07,0xef,0xfc,0xf8,0x03,0xef,0xfc,0xf8,0x01,0xf6,0xfc,0xf8,0x0f,0xf7,
|
|
0xfc,0xf8,0x8f,0xf7,0xfc,0xf8,0xe7,0xf7,0xfc,0xf8,0xf3,0xf9,0xfc,0xf8,0x79,
|
|
0xfe,0xfc,0xf8,0xbe,0xff,0xfc,0xf8,0xbf,0xff,0xfc,0xf8,0xdf,0xff,0xfc,0xf8,
|
|
0xdf,0xff,0xfc,0xf8,0xdf,0xff,0xfc,0xf0,0xff,0x7f,0xfc,0xe0,0xff,0x3f,0xfc,
|
|
0x80,0xff,0x0f,0xfc,0x80,0xff,0x07,0xfc,0x80,0xff,0x07,0xfc,0x80,0xff,0x07,
|
|
0xfc,0x80,0xff,0x07,0xfc,0x80,0xff,0x07,0xfc,0x00,0x00,0x00,0xfc,0x00,0x00,
|
|
0x00,0xfc};
|
|
|
|
Image *DefaultImage()
|
|
{
|
|
if (default_image)
|
|
return default_image;
|
|
|
|
default_pixmap = XCreatePixmapFromBitmapData(display, win, www_bits,
|
|
www_width, www_height, textColor, transparent, depth);
|
|
|
|
default_image = (Image *)malloc(sizeof(Image));
|
|
default_image->pixmap = XCreatePixmapFromBitmapData(display, win, www_bits,
|
|
www_width, www_height, textColor, transparent, depth);
|
|
default_image->width = www_width;
|
|
default_image->height = www_height;
|
|
|
|
return default_image;
|
|
}
|
|
|
|
int Brightness2Voltage(int brightness)
|
|
{
|
|
double voltage;
|
|
static double log_a = 0; /* howcome added double */
|
|
|
|
if (brightness == 0)
|
|
return 0;
|
|
|
|
if (log_a == 0)
|
|
log_a = (Gamma - 1.0) * log((double)65535); /* cast added by howcome 21/9/94 */
|
|
|
|
voltage = (log_a + log((double)brightness))/Gamma; /* cast added by howcome 21/9/94 */
|
|
|
|
return (int)(0.5 + exp(voltage));
|
|
}
|
|
|
|
int Voltage2Brightness(int voltage)
|
|
{
|
|
double brightness;
|
|
static double log_a;
|
|
|
|
if (voltage == 0)
|
|
return 0;
|
|
|
|
if (log_a == 0)
|
|
log_a = (Gamma - 1.0) * log((double)255); /* cast added by howcome 21/9/94 */
|
|
|
|
brightness = Gamma * log((double)voltage) - log_a; /* cast added by howcome 21/9/94 */
|
|
|
|
return (int)(0.5 + exp(brightness));
|
|
}
|
|
/* don't add this to images list to avoid trouble when freeing document images */
|
|
|
|
Image *MakeIcon(unsigned int depth, char *name, int width, int height, char *bits)
|
|
{
|
|
GC drawGC;
|
|
Pixmap pixmap;
|
|
XImage *ximage;
|
|
Image *image;
|
|
unsigned char *data, *p, *s;
|
|
int size, i, j, k;
|
|
unsigned int byte = 0;
|
|
|
|
size = width * height;
|
|
|
|
if (size == 0)
|
|
return NULL;
|
|
|
|
image = (Image *)malloc(sizeof(Image));
|
|
image->url = name;
|
|
image->npixels = 0;
|
|
image->pixels = 0;
|
|
image->next = NULL;
|
|
image->width = width;
|
|
image->height = height;
|
|
|
|
s = (unsigned char*)bits;
|
|
|
|
if (depth == 8)
|
|
{
|
|
p = data = (unsigned char *)malloc(size);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
byte = *s++;
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 0x01)
|
|
*p++ = textColor;
|
|
else
|
|
p = Transparent(p, j, i);
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
}
|
|
else if (depth == 16)
|
|
{
|
|
p = data = (unsigned char *)malloc(size * 2);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
byte = *s++;
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 1)
|
|
{
|
|
*p++ = (textColor >> 8) & 0xFF;
|
|
*p++ = textColor & 0xFF;
|
|
}
|
|
else
|
|
p = Transparent(p, j, i);
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
}
|
|
else if (depth == 24)
|
|
{
|
|
p = data = (unsigned char *)malloc(size * 4);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
byte = *s++;
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 1)
|
|
{
|
|
*p++ = '\0';
|
|
*p++ = (textColor >> 16) & 0xFF;
|
|
*p++ = (textColor >> 8) & 0xFF;
|
|
*p++ = textColor & 0xFF;
|
|
}
|
|
else
|
|
p = Transparent(p, j, i);
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
}
|
|
else if (depth == 4 || depth == 2 || depth == 1)
|
|
{
|
|
int ppb, bpl, shift = 0;
|
|
int newbyte;
|
|
|
|
ppb = 8/depth; /* pixels per byte */
|
|
bpl = width/ppb + (width%ppb ? 1 : 0); /* bytes per line */
|
|
|
|
p = data = (unsigned char *)malloc(bpl * height);
|
|
newbyte = 1;
|
|
|
|
for (i = 0; i < height; ++i) {
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (newbyte) {
|
|
*p = 0;
|
|
newbyte = 0;
|
|
}
|
|
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
byte = *s++;
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 0x01) {
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= textColor << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
else {
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= transparent << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
byte = byte >> 1;
|
|
}
|
|
|
|
if (shift) {
|
|
p++; /* make sure we start on a new byte for the next line */
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"Icons for display depth %d unsupported\n", depth);
|
|
return NULL;
|
|
}
|
|
|
|
if ((ximage = XCreateImage(display, DefaultVisual(display, screen),
|
|
depth, ZPixmap, 0, (char *)data,
|
|
width, height, (depth == 24 ? 32 :(depth == 16 ? 16 : 8)), 0)) == 0)
|
|
{
|
|
Warn("Failed to create XImage: %s", image->url);
|
|
Free(data);
|
|
Free(image);
|
|
return DefaultImage();
|
|
}
|
|
|
|
/* howcome 22/2/95: do we need to set these?? */
|
|
|
|
ximage->byte_order = MSBFirst;
|
|
|
|
ximage->bitmap_bit_order = BitmapBitOrder(display);
|
|
|
|
if ((pixmap = XCreatePixmap(display, win, width, height, depth)) == 0)
|
|
{
|
|
Warn("Failed to create Pixmap: %s", image->url);
|
|
XDestroyImage(ximage); /* also free's image data */
|
|
Free(image);
|
|
return DefaultImage();
|
|
}
|
|
|
|
drawGC = XCreateGC(display, pixmap, 0, 0);
|
|
XSetFunction(display, drawGC, GXcopy);
|
|
XPutImage(display, pixmap, drawGC, ximage, 0, 0, 0, 0, width, height);
|
|
XFreeGC(display, drawGC);
|
|
XDestroyImage(ximage); /* also free's image data */
|
|
|
|
/* janet 27/07/95: image not always freed! */
|
|
Free(image);
|
|
|
|
image = (Image *)malloc(sizeof(Image));
|
|
image->url = name;
|
|
image->npixels = 0;
|
|
image->pixels = 0;
|
|
image->next = NULL;
|
|
image->width = width;
|
|
image->height = height;
|
|
image->pixmap = pixmap;
|
|
return image;
|
|
}
|
|
|
|
void MakeIcons(unsigned int depth)
|
|
{
|
|
note_image = MakeIcon(depth, "note", note_width, note_height, note_bits);
|
|
caution_image = MakeIcon(depth, "caution", caution_width, caution_height, caution_bits);
|
|
warning_image = MakeIcon(depth, "warning", warning_width, warning_height, warning_bits);
|
|
}
|
|
|
|
unsigned char *gamma_table=NULL;
|
|
|
|
|
|
static unsigned int
|
|
range (unsigned int val, unsigned int max)
|
|
{
|
|
return (val > max) ? max : val;
|
|
}
|
|
|
|
void
|
|
build_gamma_table()
|
|
{
|
|
if (!gamma_table) {
|
|
int i;
|
|
double file_gamma = 1.0/2.2;
|
|
double g = 1.0 / (file_gamma * Gamma);
|
|
|
|
gamma_table = (unsigned char *) malloc(256 * sizeof(char));
|
|
for (i = 0; i < 256; i++)
|
|
gamma_table[i] = (unsigned char)range((pow((double)i / 255.0, g) * 255.0), 255);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
free_gamma_table()
|
|
{
|
|
if(gamma_table){
|
|
free(gamma_table);
|
|
gamma_table=NULL;
|
|
}
|
|
}
|
|
|
|
int AllocGreyScale(void)
|
|
{
|
|
unsigned long g;
|
|
XColor color;
|
|
|
|
greymap[0] = BlackPixel(display, screen);
|
|
greymap[15] = WhitePixel(display, screen);
|
|
|
|
/* mycmap[128 & 0] = BlackPixel(display, screen);
|
|
mycmap[128 & 15] = WhitePixel(display, screen);
|
|
*/
|
|
for (g = !OwnColorMap; g < 16+OwnColorMap; ++g)
|
|
{
|
|
color.red = color.green = color.blue = (g * 65535)/15;
|
|
|
|
/* map brightness values into voltages for Gamma correction */
|
|
|
|
color.red = Brightness2Voltage(color.red);
|
|
color.green = Brightness2Voltage(color.green);
|
|
color.blue = Brightness2Voltage(color.blue);
|
|
|
|
if (XAllocColor(display, colormap, &color) == 0)
|
|
{
|
|
fprintf(stderr, "Can't allocate standard grey palette\n");
|
|
|
|
while (g > 1)
|
|
XFreeColors(display, colormap, &(greymap[--g]), 1, 0);
|
|
|
|
return 0;
|
|
}
|
|
greymap[g] = color.pixel;
|
|
/* mycmap[128 & g] = color.pixel;*/
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int AllocStandardColors(void)
|
|
{
|
|
unsigned long i;
|
|
XColor colors[128]; /* howcome 5/10/94 */
|
|
int status[128]; /* howcome 5/10/94 */
|
|
XColor color;
|
|
int color_ok=1;
|
|
|
|
stdcmap[0] = BlackPixel(display, screen);
|
|
stdcmap[127] = WhitePixel(display, screen);
|
|
|
|
mycmap[0] = BlackPixel(display, screen);
|
|
mycmap[127] = WhitePixel(display, screen);
|
|
|
|
for (i = 0; i < 128; ++i)
|
|
{
|
|
#if 0
|
|
double gammaC = 0.7;
|
|
color.red = /*(i & 0x3) * 65535/3 ; */ pow((((double)(i & 0x3))/3.0), gammaC)*65535;
|
|
color.green = /*((i >> 2) & 0x7) * 65535/7 ;*/ pow((((double)((i >> 2) & 0x7))/7.0), gammaC)*65535;
|
|
color.blue = /*((i >> 5) & 0x3) * 65535/3 ;*/ pow((((double)((i >> 5) & 0x3))/3.0), gammaC)*65535;
|
|
#endif
|
|
color.red = (i & 0x3) * 65535/3;
|
|
color.green = ((i >> 2) & 0x7) * 65535/7;
|
|
color.blue = ((i >> 5) & 0x3) * 65535/3;
|
|
|
|
if (COLOR_TRACE)
|
|
fprintf(stderr,"AllocStandardColors exact %d %d %d\n", (color.red >> 8), (color.green >> 8), (color.blue >> 8));
|
|
|
|
/* howcome 5/10/94: added support for XAllocColors which will
|
|
speed things up. */
|
|
|
|
/* map brightness values into voltages for Gamma correction */
|
|
|
|
colors[i].red = Brightness2Voltage(color.red);
|
|
colors[i].green = Brightness2Voltage(color.green);
|
|
colors[i].blue = Brightness2Voltage(color.blue);
|
|
#if 0
|
|
colors[i].red = color.red;
|
|
colors[i].green = color.green;
|
|
colors[i].blue = color.blue;
|
|
#endif
|
|
if (COLOR_TRACE)
|
|
fprintf(stderr,"AllocStandardColors %d %d %d\n", (colors[i].red >> 8), (colors[i].green >> 8), (colors[i].blue >> 8));
|
|
}
|
|
|
|
/* howcome 5/10/94: here comes the one and only call to XAllocColors */
|
|
|
|
if (!OwnColorMap)
|
|
{
|
|
if (XAllocColors(display, colormap, colors, i, status)) {
|
|
for (i = 1; i < 127; i++ ) {
|
|
stdcmap[i] = colors[i].pixel;
|
|
mycmap[i] = colors[i].pixel;
|
|
}
|
|
} else {
|
|
int j;
|
|
for(j = 1; j < i ; j++)
|
|
if (status[j])
|
|
XFreeColors( display, colormap, &colors[j].pixel, 1, 0L );
|
|
OwnColorMap = 1; /* --Spif 25-Oct-95 -cm flag now works */
|
|
color_ok=0;
|
|
}
|
|
};
|
|
|
|
/* howcome 10/8/05: added support for own colormap */
|
|
|
|
if (OwnColorMap) {
|
|
int j;
|
|
if(!color_ok) {
|
|
fprintf(stderr,"Can't alloc colors, creating new colormap..\n");
|
|
for(i=1; i < 15 ; i++)
|
|
XFreeColors(display, colormap, &(greymap[i]), 1, 0);
|
|
};
|
|
colormap = XCreateColormap(display, RootWindow(display, screen),
|
|
visual, AllocNone);
|
|
AllocGreyScale();
|
|
for(j=0;j<128;j++)
|
|
{
|
|
if (XAllocColor(display, colormap, &colors[j]) == 0)
|
|
{
|
|
int g;
|
|
fprintf(stderr, "FATAL ERROR:Can't allocate my own palette!!\n");
|
|
g=j;
|
|
while (g > 1)
|
|
XFreeColors(display, colormap, &(stdcmap[--g]), 1, 0);
|
|
return 0;
|
|
};
|
|
stdcmap[j] = colors[j].pixel;
|
|
mycmap[j] = colors[j].pixel;
|
|
}
|
|
|
|
return 1; /* assume success, what could go wrong? */
|
|
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int SupportTrueColor(void)
|
|
{
|
|
long visual_info_mask;
|
|
int number_visuals, i, flag;
|
|
XVisualInfo *visual_array, visual_info_template;
|
|
|
|
visual_info_template.screen = DefaultScreen(display);
|
|
visual_info_mask = VisualClassMask | VisualScreenMask;
|
|
|
|
visual_info_template.class = TrueColor;
|
|
visual_array = XGetVisualInfo(display, visual_info_mask,
|
|
&visual_info_template,
|
|
&number_visuals);
|
|
|
|
for (i = flag = 0; i < number_visuals; ++i)
|
|
{
|
|
if (visual_array[i].depth == 16)
|
|
{
|
|
long int maskval;
|
|
int j=0, k;
|
|
|
|
maskval = (*visual).blue_mask;
|
|
while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
|
|
maskval = (*visual).blue_mask;
|
|
BPixelMask = 0;
|
|
for(k=0; k<16; k++)
|
|
{
|
|
if(maskval & 1)
|
|
{
|
|
if(!BPixelMask)
|
|
BPixelMask = 1;
|
|
else
|
|
BPixelMask += BPixelMask + 1;
|
|
};
|
|
maskval = maskval >> 1;
|
|
}
|
|
j=0;
|
|
maskval = (*visual).green_mask;
|
|
while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
|
|
GPixelShift = j;
|
|
GPixelMask = 0;
|
|
for(k=0; k<16; k++)
|
|
{
|
|
if(maskval & 1)
|
|
{
|
|
if(!GPixelMask)
|
|
GPixelMask = 1;
|
|
else
|
|
GPixelMask += GPixelMask + 1;
|
|
};
|
|
maskval = maskval >> 1;
|
|
}
|
|
j=0;
|
|
maskval = (*visual).red_mask;
|
|
while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
|
|
RPixelShift = j;
|
|
RPixelMask = 0;
|
|
for(k=0; k<16; k++)
|
|
{
|
|
if(maskval & 1)
|
|
{
|
|
if(!RPixelMask)
|
|
RPixelMask = 1;
|
|
else
|
|
RPixelMask += RPixelMask + 1;
|
|
};
|
|
maskval = maskval >> 1;
|
|
};
|
|
flag = 1;
|
|
}
|
|
if (visual_array[i].depth == 24)
|
|
{
|
|
long int maskval;
|
|
int j=0;
|
|
|
|
maskval = (*visual).blue_mask;
|
|
while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
|
|
BPixelShift = j;
|
|
j=0;
|
|
maskval = (*visual).green_mask;
|
|
while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
|
|
GPixelShift = j;
|
|
j=0;
|
|
maskval = (*visual).red_mask;
|
|
while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
|
|
RPixelShift = j;
|
|
flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
XFree((void *)visual_array);
|
|
return flag;
|
|
}
|
|
|
|
int InitImaging(int ColorStyle)
|
|
{
|
|
imaging = MONO;
|
|
|
|
build_gamma_table();
|
|
|
|
greymap[0] = BlackPixel(display, screen);
|
|
greymap[15] = WhitePixel(display, screen);
|
|
|
|
if (ColorStyle == MONO)
|
|
{
|
|
imaging = ColorStyle;
|
|
return imaging;
|
|
}
|
|
|
|
if (ColorStyle == COLOR888 && SupportTrueColor())
|
|
{
|
|
imaging = ColorStyle;
|
|
return imaging;
|
|
}
|
|
|
|
if(OwnColorMap)
|
|
if (AllocStandardColors())
|
|
{
|
|
imaging = COLOR232;
|
|
return imaging;
|
|
};
|
|
|
|
if (AllocGreyScale())
|
|
{
|
|
imaging = GREY4;
|
|
|
|
if (ColorStyle == GREY4)
|
|
return imaging;
|
|
|
|
if (AllocStandardColors())
|
|
imaging = COLOR232;
|
|
} else
|
|
if(OwnColorMap)
|
|
if (AllocStandardColors())
|
|
imaging = COLOR232;
|
|
return imaging;
|
|
}
|
|
|
|
void ReportVisuals(void)
|
|
{
|
|
long visual_info_mask;
|
|
int number_visuals, i;
|
|
XVisualInfo *visual_array, visual_info_template;
|
|
|
|
visual_info_template.screen = DefaultScreen(display);
|
|
|
|
visual_info_mask = VisualClassMask | VisualScreenMask;
|
|
|
|
printf("TrueColor:\n");
|
|
|
|
visual_info_template.class = TrueColor;
|
|
visual_array = XGetVisualInfo(display, visual_info_mask,
|
|
&visual_info_template,
|
|
&number_visuals);
|
|
|
|
for (i = 0; i < number_visuals; ++i)
|
|
{
|
|
printf(" visual Id 0x%x\n", visual_array[i].visualid);
|
|
printf(" depth = %d, bits per rgb = %d, size = %d\n", visual_array[i].depth,
|
|
visual_array[i].bits_per_rgb, visual_array[i].colormap_size);
|
|
printf(" rgb masks %lx, %lx, %lx\n", visual_array[i].red_mask,
|
|
visual_array[i].green_mask, visual_array[i].blue_mask);
|
|
}
|
|
|
|
XFree((void *)visual_array);
|
|
|
|
printf("DirectColor:\n");
|
|
|
|
visual_info_template.class = DirectColor;
|
|
visual_array = XGetVisualInfo(display, visual_info_mask,
|
|
&visual_info_template,
|
|
&number_visuals);
|
|
|
|
for (i = 0; i < number_visuals; ++i)
|
|
{
|
|
printf(" visual Id 0x%x\n", visual_array[i].visualid);
|
|
printf(" depth = %d, bits per rgb = %d, size = %d\n", visual_array[i].depth,
|
|
visual_array[i].bits_per_rgb, visual_array[i].colormap_size);
|
|
printf(" rgb masks %lx, %lx, %lx\n", visual_array[i].red_mask,
|
|
visual_array[i].green_mask, visual_array[i].blue_mask);
|
|
}
|
|
|
|
XFree((void *)visual_array);
|
|
|
|
printf("PseudoColor:\n");
|
|
|
|
visual_info_template.class = PseudoColor;
|
|
visual_array = XGetVisualInfo(display, visual_info_mask,
|
|
&visual_info_template,
|
|
&number_visuals);
|
|
|
|
for (i = 0; i < number_visuals; ++i)
|
|
{
|
|
printf(" visual Id 0x%x\n", visual_array[i].visualid);
|
|
printf(" depth = %d, bits per rgb = %d, size = %d\n", visual_array[i].depth,
|
|
visual_array[i].bits_per_rgb, visual_array[i].colormap_size);
|
|
printf(" rgb masks %lx, %lx, %lx\n", visual_array[i].red_mask,
|
|
visual_array[i].green_mask, visual_array[i].blue_mask);
|
|
}
|
|
|
|
XFree((void *)visual_array);
|
|
}
|
|
|
|
void ReportStandardColorMaps(Atom which_map)
|
|
{
|
|
XStandardColormap *std_colormaps;
|
|
int i, number_colormaps;
|
|
char *atom_name;
|
|
|
|
if (XGetRGBColormaps(display, RootWindow(display, screen),
|
|
&std_colormaps, &number_colormaps, which_map) != 0)
|
|
{
|
|
atom_name = XGetAtomName(display, which_map);
|
|
printf("\nPrinting %d standard colormaps for %s\n",
|
|
number_colormaps, atom_name);
|
|
XFree(atom_name);
|
|
|
|
for (i = 0; i < number_colormaps; ++i)
|
|
{
|
|
printf("\tColormap: 0x%x\n", std_colormaps[i].colormap);
|
|
printf("\tMax cells (rgb): %d, %d, %d\n",
|
|
std_colormaps[i].red_max,
|
|
std_colormaps[i].green_max,
|
|
std_colormaps[i].blue_max);
|
|
printf("\tMultipliers: %d, %d, %d\n",
|
|
std_colormaps[i].red_mult,
|
|
std_colormaps[i].green_mult,
|
|
std_colormaps[i].blue_mult);
|
|
printf("\tBase pixel: %d\n", std_colormaps[i].base_pixel);
|
|
printf("\tVisual Id 0x%x, Kill Id 0x%x\n",
|
|
std_colormaps[i].visualid,
|
|
std_colormaps[i].killid);
|
|
}
|
|
|
|
XFree((void *)std_colormaps);
|
|
}
|
|
}
|
|
|
|
XColor paperrgb[3];
|
|
|
|
/* Init paperrgb */
|
|
void InitPaperRGB ()
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<3; i++) {
|
|
int r=0, g=0, b=0;
|
|
switch(i) {
|
|
case 0:
|
|
r=230; g=218; b=194;
|
|
break;
|
|
case 1:
|
|
r=220; g=209; b=186;
|
|
break;
|
|
case 2:
|
|
r=210; g=199; b=177;
|
|
break;
|
|
}
|
|
|
|
paperrgb[i].red=gamma_table[r];
|
|
paperrgb[i].green=gamma_table[g];
|
|
paperrgb[i].blue=gamma_table[b];
|
|
}
|
|
}
|
|
|
|
|
|
/* Barely used colormap */
|
|
XColor papercols[256];
|
|
|
|
|
|
/* create a textured background as paper */
|
|
unsigned char *CreateBackground(unsigned int width, unsigned int height, unsigned int depth)
|
|
{
|
|
unsigned char *data, *p;
|
|
int size, i, j;
|
|
unsigned long cs[3]; /* howcome 21/9/94 */
|
|
unsigned long int ulp;
|
|
|
|
if (depth == 8)
|
|
{
|
|
/* howcome 4/10/94: changed last arg to GetColor */
|
|
|
|
int i;
|
|
for (i=0; i<3; i++) {
|
|
int r, g, b;
|
|
r=paperrgb[i].red;
|
|
g=paperrgb[i].green;
|
|
b=paperrgb[i].blue;
|
|
if (!GetColor(r, g, b, &cs[i]))
|
|
return NULL;
|
|
paperrgb[i].pixel=cs[i];
|
|
papercols[cs[i]].red=r;
|
|
papercols[cs[i]].green=g;
|
|
papercols[cs[i]].blue=b;
|
|
}
|
|
|
|
size = width * height;
|
|
}
|
|
else if (depth == 24)
|
|
size = width * height * 4;
|
|
else if (depth == 16)
|
|
size = width * height *2;
|
|
else
|
|
return NULL;
|
|
|
|
p = data = (unsigned char *)malloc(size);
|
|
|
|
if (data == NULL)
|
|
return NULL;
|
|
|
|
srand(0x6000);
|
|
|
|
if (depth == 8)
|
|
{
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
/* howcome 21/9/94: rand returns different ranges on different platforms, therefore: */
|
|
|
|
*p++ = paperrgb[rand() % 3].pixel;
|
|
}
|
|
}
|
|
else if (depth == 24)
|
|
{
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
int col,r,g,b;
|
|
|
|
col=rand() % 3;
|
|
|
|
r=paperrgb[col].red;
|
|
g=paperrgb[col].green;
|
|
b=paperrgb[col].blue;
|
|
|
|
GetColor(r, g, b, &ulp);
|
|
|
|
*p++ = '\0';
|
|
*p++ = (ulp >> 16) & 0xff;
|
|
*p++ = (ulp >> 8) & 0xff;
|
|
*p++ = ulp & 0xff;
|
|
#if 0
|
|
*p++ = '\0';
|
|
*p++ = paperrgb[col].red;
|
|
*p++ = paperrgb[col].green;
|
|
*p++ = paperrgb[col].blue;
|
|
#endif
|
|
}
|
|
} else if (depth == 16)
|
|
{
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
int col,r,g,b;
|
|
|
|
col=rand() % 3;
|
|
r=paperrgb[col].red;
|
|
g=paperrgb[col].green;
|
|
b=paperrgb[col].blue;
|
|
|
|
GetColor(r, g, b, &ulp);
|
|
|
|
*p++ = ((char*)&ulp)[1];
|
|
*p++ = ((char*)&ulp)[0];
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
#if 0 /* used to allow for nested comments */
|
|
/* XPM */
|
|
/********************************************************/
|
|
/** (c) Copyright Hewlett-Packard Company, 1992. **/
|
|
/********************************************************/
|
|
static char ** arizona.l.px = {
|
|
/* width height ncolors cpp [x_hot y_hot] */
|
|
"28 38 13 1",
|
|
/* colors */
|
|
" s iconColor2 m white c white",
|
|
". s iconGray2 m white c #c8c8c8c8c8c8",
|
|
"X s iconColor1 m black c black",
|
|
"o s iconGray6 m black c #646464646464",
|
|
"O s iconGray3 m white c #afafafafafaf",
|
|
"+ s iconColor3 m black c red",
|
|
"@ s iconColor8 m white c magenta",
|
|
"# s iconGray4 m white c #969696969696",
|
|
"$ s iconGray5 m black c #7d7d7d7d7d7d",
|
|
"% s iconColor6 m white c yellow",
|
|
"& s iconGray1 m white c #e1e1e1e1e1e1",
|
|
"* s iconColor4 m black c green",
|
|
"= s bottomShadowColor m black c #646464646464",
|
|
/* pixels */
|
|
" ",
|
|
" ..........................X",
|
|
" ..............oo..........X",
|
|
" .........OOOoo+@@oooOOOOOOX",
|
|
" .....OOOoooo@####@+ooooo..X",
|
|
" ..ooo#oo+@###$$$$#####OOO.X",
|
|
" ..OOOOOO###$$....$$#@+ooo.X",
|
|
" .......+@#$.%%%%%%.$###OOOX",
|
|
" ..o.ooo..$.%%%%%%%%%$#@+ooX",
|
|
and so on, ending with:
|
|
" XXXXXXXXXXXXXXXXXXXXXXXXXXX"};
|
|
#endif
|
|
|
|
#define NEXTCHAR(s) (*s ? *s++ : '\0')
|
|
|
|
static char *FindCh(char *s, char ch)
|
|
{
|
|
char c;
|
|
|
|
for (;;)
|
|
{
|
|
c = NEXTCHAR(s);
|
|
|
|
if (c == ch || c == '\0')
|
|
return s;
|
|
}
|
|
}
|
|
|
|
/* *c to first char and return last word */
|
|
|
|
static char *ReadColor(char *s, char **name, int *ch)
|
|
{
|
|
char *p;
|
|
int c;
|
|
static char line[256];
|
|
|
|
s = FindCh(s, '"');
|
|
*ch = NEXTCHAR(s);
|
|
p = line;
|
|
|
|
while ((c = NEXTCHAR(s)) != '"' && c != '\0' && p < line+255)
|
|
*p++ = c;
|
|
|
|
*p = '\0';
|
|
p = strrchr(line, ' ');
|
|
|
|
if (p)
|
|
++p;
|
|
|
|
*name = p;
|
|
return s;
|
|
}
|
|
|
|
unsigned char *Transparent(unsigned char *p, int x, int y)
|
|
{
|
|
unsigned int i;
|
|
unsigned char *s;
|
|
|
|
if (tileData)
|
|
{
|
|
x = x % tileWidth;
|
|
y = y % tileHeight;
|
|
i = y * tileWidth + x;
|
|
|
|
if (depth == 24)
|
|
{
|
|
s = tileData + 4 * i;
|
|
|
|
*p++ = *s++;
|
|
*p++ = *s++;
|
|
*p++ = *s++;
|
|
*p++ = *s++;
|
|
|
|
return p;
|
|
}
|
|
|
|
if (depth == 16)
|
|
{
|
|
s = tileData + 2 * i;
|
|
|
|
*p++ = *s++;
|
|
*p++ = *s++;
|
|
|
|
return p;
|
|
};
|
|
|
|
*p++ = gamma_table[tileData[i]];
|
|
return p;
|
|
}
|
|
|
|
if (depth == 24)
|
|
{
|
|
*p++ = '\0';
|
|
*p++ = (transparent >> 16) & 0xFF;
|
|
*p++ = (transparent >> 8) & 0xFF;
|
|
*p++ = transparent & 0xFF;
|
|
return p;
|
|
}
|
|
|
|
if (depth == 16)
|
|
{
|
|
*p++ = (transparent >> 8) & 0xFF;
|
|
*p++ = transparent & 0xFF;
|
|
return p;
|
|
};
|
|
|
|
*p++ = transparent;
|
|
return p;
|
|
}
|
|
|
|
/* load data from an XPM file and allocate colors */
|
|
|
|
char *LoadXpmImage(Image *image, Block *bp, unsigned int depth)
|
|
{
|
|
int c, i, j, cr, cg, cb, r, g, b, ncolors, size, map[256];
|
|
unsigned int width, height;
|
|
/* unsigned long pixel, *pixdata; */ /* janet 21/07/95: not used */
|
|
unsigned char *data = NULL, *p;
|
|
unsigned long ccolor;
|
|
char *name, *s;
|
|
Color *colors, color;
|
|
XColor xcolor;
|
|
|
|
s = bp->buffer + bp->next;
|
|
|
|
s = FindCh(s, '"');
|
|
sscanf(s, "%d %d %d", &width, &height, &ncolors);
|
|
s = FindCh(s, '\n');
|
|
|
|
size = width * height;
|
|
image->width = width;
|
|
image->height = height;
|
|
|
|
if (size == 0 || ncolors == 0)
|
|
return NULL;
|
|
|
|
|
|
if (depth != 8 && depth != 24 && depth != 4 && depth != 2 && depth != 1)
|
|
{
|
|
printf("Display depth %d unsupported\n", depth);
|
|
return NULL;
|
|
}
|
|
|
|
image->npixels = 0;
|
|
image->pixels = 0; /*(unsigned long *)malloc(ncolors * sizeof(unsigned long)); */
|
|
|
|
colors = (Color *)malloc(ncolors * sizeof(Color));
|
|
|
|
for (i = 0; i < 256; ++i)
|
|
map[i] = -1;
|
|
|
|
for (i = 0; i < ncolors; ++i)
|
|
{
|
|
s = ReadColor(s, &name, &c);
|
|
|
|
if (XParseColor(display, colormap, name, &xcolor) == 0)
|
|
{
|
|
map[c] = -1;
|
|
continue;
|
|
}
|
|
|
|
map[c] = i;
|
|
r = xcolor.red >> 8;
|
|
g = xcolor.green >> 8;
|
|
b = xcolor.blue >> 8;
|
|
|
|
/* apply Gamma correction to map voltages to brightness values */
|
|
|
|
if (imaging != COLOR888)
|
|
{
|
|
/*
|
|
r = gamma_table[r];
|
|
g = gamma_table[g];
|
|
b = gamma_table[b];*/
|
|
r = Voltage2Brightness(r);
|
|
g = Voltage2Brightness(g);
|
|
b = Voltage2Brightness(b);
|
|
}
|
|
|
|
colors[i].red = r;
|
|
colors[i].green = g;
|
|
colors[i].blue = b;
|
|
colors[i].grey = (3*r + 6*g + b)/10;
|
|
}
|
|
|
|
|
|
if (depth == 8)
|
|
{
|
|
p = data = malloc(size);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
{
|
|
s = FindCh(s, '"');
|
|
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
c = *s++;
|
|
c = map[c];
|
|
|
|
if (c < 0)
|
|
{
|
|
p = Transparent(p, j, i);
|
|
continue;
|
|
}
|
|
|
|
color = colors[c];
|
|
c = ((i % 16) << 4) + (j % 16);
|
|
|
|
if (imaging == COLOR232)
|
|
{
|
|
cr = color.red;
|
|
cg = color.green;
|
|
cb = color.blue;
|
|
|
|
if (cr == cg && cg == cb)
|
|
{
|
|
cg = color.grey;
|
|
g = cg & 0xF0;
|
|
|
|
if (cg - g > Magic16[c])
|
|
g += 16;
|
|
|
|
g = min(g, 0xF0);
|
|
*p++ = greymap[g >> 4];
|
|
}
|
|
else
|
|
{
|
|
r = cr & 0xC0;
|
|
g = cg & 0xE0;
|
|
b = cb & 0xC0;
|
|
|
|
if (cr - r > Magic64[c])
|
|
r += 64;
|
|
|
|
if (cg - g > Magic32[c])
|
|
g += 32;
|
|
|
|
if (cb - b > Magic64[c])
|
|
b += 64;
|
|
|
|
r = min(r, 255) & 0xC0;
|
|
g = min(g, 255) & 0xE0;
|
|
b = min(b, 255) & 0xC0;
|
|
|
|
*p++ = stdcmap[(r >> 6) | (g >> 3) | (b >> 1)];
|
|
}
|
|
}
|
|
else if (imaging == GREY4)
|
|
{
|
|
cg = color.grey;
|
|
g = cg & 0xF0;
|
|
|
|
if (cg - g > Magic16[c])
|
|
g += 16;
|
|
|
|
g = min(g, 0xF0);
|
|
*p++ = greymap[g >> 4];
|
|
}
|
|
else /* MONO */
|
|
{
|
|
if (color.grey < Magic256[c])
|
|
*p++ = greymap[0];
|
|
else
|
|
*p++ = greymap[15];
|
|
}
|
|
}
|
|
|
|
s = FindCh(s, '\n');
|
|
}
|
|
}
|
|
else if (depth == 24)
|
|
{
|
|
p = data = malloc(size * 4);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
{
|
|
s = FindCh(s, '"');
|
|
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
if ((c = map[*s++]) < 0)
|
|
{
|
|
p = Transparent(p, j, i);
|
|
continue;
|
|
};
|
|
|
|
color = colors[c];
|
|
*p++ = '\0';
|
|
*p++ = color.red;
|
|
*p++ = color.green;
|
|
*p++ = color.blue;
|
|
}
|
|
|
|
s = FindCh(s, '\n');
|
|
}
|
|
}
|
|
else if (depth == 16)
|
|
{
|
|
p = data = malloc(size * 2);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
{
|
|
s = FindCh(s, '"');
|
|
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
if ((c = map[*s++]) < 0)
|
|
{
|
|
p = Transparent(p, j, i);
|
|
continue;
|
|
};
|
|
|
|
color = colors[c];
|
|
GetColor(color.red, color.green, color.blue, &ccolor);
|
|
*p++ = (ccolor >> 8 )& 0xff;
|
|
*p++ = (ccolor & 0xff);
|
|
}
|
|
s = FindCh(s, '\n');
|
|
}
|
|
}
|
|
else if (depth == 1 || depth == 2 || depth == 4) /* howcome added support for these */
|
|
{
|
|
int ppb, bpl, shift = 0;
|
|
int newbyte;
|
|
|
|
ppb = 8/depth; /* pixels per byte */
|
|
bpl = width/ppb + (width%ppb ? 1 : 0); /* bytes per line */
|
|
|
|
p = data = (unsigned char *)malloc(bpl * height);
|
|
newbyte = 1;
|
|
|
|
for (i = 0; i < height; ++i)
|
|
{
|
|
s = FindCh(s, '"');
|
|
|
|
for (j = 0; j < width; ++j)
|
|
{
|
|
if (newbyte) {
|
|
*p = 0;
|
|
newbyte = 0;
|
|
}
|
|
|
|
c = *s++;
|
|
c = map[c];
|
|
|
|
if (c < 0)
|
|
{
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= transparent << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
*p = 0;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
color = colors[c];
|
|
c = ((i % 16) << 4) + (j % 16);
|
|
|
|
if (imaging == COLOR232)
|
|
{
|
|
cr = color.red;
|
|
cg = color.green;
|
|
cb = color.blue;
|
|
|
|
if (cr == cg && cg == cb)
|
|
{
|
|
cg = color.grey;
|
|
g = cg & 0xF0;
|
|
|
|
if (cg - g > Magic16[c])
|
|
g += 16;
|
|
|
|
g = min(g, 0xF0);
|
|
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= greymap[g >> 4] << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
r = cr & 0xC0;
|
|
g = cg & 0xE0;
|
|
b = cb & 0xC0;
|
|
|
|
if (cr - r > Magic64[c])
|
|
r += 64;
|
|
|
|
if (cg - g > Magic32[c])
|
|
g += 32;
|
|
|
|
if (cb - b > Magic64[c])
|
|
b += 64;
|
|
|
|
r = min(r, 255) & 0xC0;
|
|
g = min(g, 255) & 0xE0;
|
|
b = min(b, 255) & 0xC0;
|
|
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= stdcmap[(r >> 6) | (g >> 3) | (b >> 1)] << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
}
|
|
else if (imaging == GREY4)
|
|
{
|
|
cg = color.grey;
|
|
g = cg & 0xF0;
|
|
|
|
if (cg - g > Magic16[c])
|
|
g += 16;
|
|
|
|
g = min(g, 0xF0);
|
|
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= greymap[g >> 4] << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
else /* MONO */
|
|
{
|
|
if (color.grey < Magic256[c]) {
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= greymap[0] << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
else {
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= greymap[15] << shift;
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
s = FindCh(s, '\n');
|
|
|
|
if (shift) {
|
|
p++; /* make sure we start on a new byte for the next line */
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
Free(colors);
|
|
return (char *)data;
|
|
}
|
|
|
|
/*
|
|
Load data from an XBM file
|
|
|
|
#define back_width 20
|
|
#define back_height 23
|
|
static char back_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f,
|
|
0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f,
|
|
0x00, 0x80, 0x0f, 0x60, 0x80, 0x0f, 0x70, 0x80, 0x0f, 0x78, 0x00, 0x00,
|
|
0xfc, 0xff, 0x0f, 0xfe, 0xff, 0x07, 0xff, 0xff, 0x03, 0xfe, 0xff, 0x01,
|
|
0xfc, 0xff, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
So find line start with #define and read last number as width.
|
|
Repeat to get height. Should really look at names to avoid problems
|
|
if order is swapped, but probably won't be necessary.
|
|
|
|
Number of bytes of data is: ((height * width) + 7)/8
|
|
|
|
Then skip to '{' char and then start reading data:
|
|
|
|
whitespace or ',' followed by hex number
|
|
*/
|
|
|
|
char *LoadXbmImage(Image *image, Block *bp, unsigned int depth)
|
|
{
|
|
char *s;
|
|
int c, i, j, k, size;
|
|
unsigned int width, height, byte;
|
|
unsigned char *data, *p;
|
|
|
|
s = (char *)bp->buffer + bp->next;
|
|
|
|
s = FindCh(s, '#'); /* find #define */
|
|
s = FindCh(s, ' '); /* find 1st space char */
|
|
s = FindCh(s, ' '); /* find 2nd space char */
|
|
sscanf(s, "%d", &width); /* and read width */
|
|
s = FindCh(s, '#'); /* find next #define */
|
|
s = FindCh(s, ' '); /* find 1st space char */
|
|
s = FindCh(s, ' '); /* find 2nd space char */
|
|
sscanf(s, "%d", &height); /* and read width */
|
|
s = FindCh(s, '{'); /* find opening brace for data */
|
|
|
|
size = width * height;
|
|
image->width = width;
|
|
image->height = height;
|
|
|
|
if (size == 0)
|
|
return NULL;
|
|
|
|
image->npixels = 0;
|
|
image->pixels = 0;
|
|
|
|
if (depth == 8)
|
|
{
|
|
p = data = (unsigned char *)malloc(size);
|
|
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
s = FindCh(s, '0');
|
|
sscanf(s+1, "%x", &byte); /* howcome 5/11/94: '-1' changed to '+1' since some don't like 0x */
|
|
while ((c = NEXTCHAR(s)) != ',' && c != '}');
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 0x01)
|
|
*p++ = textColor;
|
|
else
|
|
p = Transparent(p, j, i);
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
}
|
|
else if (depth == 24)
|
|
{
|
|
p = data = (unsigned char *)malloc(size * 4);
|
|
|
|
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
s = FindCh(s, '0');
|
|
sscanf(s-1, "%x", &byte);
|
|
while ((c = NEXTCHAR(s)) != ',' && c != '}');
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 1)
|
|
{
|
|
*p++ = '\0';
|
|
*p++ = (textColor >> 16) & 0xFF;
|
|
*p++ = (textColor >> 8) & 0xFF;
|
|
*p++ = textColor & 0xFF;
|
|
}
|
|
else
|
|
p = Transparent(p, j, i);
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
}
|
|
else if (depth == 16)
|
|
{
|
|
p = data = (unsigned char *)malloc(size * 2);
|
|
|
|
|
|
for (i = 0; i < height; ++i)
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
s = FindCh(s, '0');
|
|
sscanf(s-1, "%x", &byte);
|
|
while ((c = NEXTCHAR(s)) != ',' && c != '}');
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 1)
|
|
{
|
|
*p++ = (textColor >> 8) & 0xFF;
|
|
*p++ = textColor & 0xFF;
|
|
}
|
|
else
|
|
p = Transparent(p, j, i);
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
}
|
|
else if (depth == 1 || depth == 2 || depth == 4) /* howcome added support for these */
|
|
{
|
|
int ppb, bpl, shift;
|
|
int newbyte;
|
|
|
|
ppb = 8/depth; /* pixels per byte */
|
|
bpl = width/ppb + (width%ppb ? 1 : 0); /* bytes per line */
|
|
|
|
p = data = (unsigned char *)malloc(bpl * height);
|
|
newbyte = 1;
|
|
|
|
for (i = 0; i < height; ++i) {
|
|
for (j = 0, k= 8; j < width; ++j)
|
|
{
|
|
if (newbyte) {
|
|
*p = 0;
|
|
newbyte = 0;
|
|
}
|
|
|
|
if (++k > 8) /* need to read next 8 pixel values */
|
|
{
|
|
s = FindCh(s, '0');
|
|
sscanf(s+1, "%x", &byte); /* howcome 5/11/94: '-1' changed to '+1' since some don't like 0x */
|
|
while ((c = NEXTCHAR(s)) != ',' && c != '}');
|
|
k = 1;
|
|
}
|
|
|
|
if (byte & 0x01) {
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= textColor << shift;
|
|
}
|
|
else {
|
|
shift = (((7 - (j % 8)) % ppb) * depth);
|
|
*p |= transparent << shift;
|
|
}
|
|
|
|
if (shift == 0) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
|
|
byte = byte >> 1;
|
|
}
|
|
|
|
if (shift) {
|
|
p++;
|
|
newbyte = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Warn("image/x-xbitmap unsupported for depth %d", depth);
|
|
return NULL;
|
|
}
|
|
|
|
return (char *)data;
|
|
}
|
|
|
|
|
|
Image *ProcessLoadedImage(Doc *doc)
|
|
{
|
|
char *data;
|
|
Image *image;
|
|
Block block;
|
|
unsigned int width, height;
|
|
XImage *ximage;
|
|
Pixmap pixmap;
|
|
GC drawGC;
|
|
HTAtom *a = NULL;
|
|
|
|
if (doc && doc->anchor)
|
|
a = HTAnchor_format(doc->anchor->parent);
|
|
|
|
image = (Image *)malloc(sizeof(Image));
|
|
image->npixels = 0;
|
|
|
|
block.next = 0; /*NewDoc.hdrlen; */
|
|
block.size = doc->loaded_length; /* NewDoc.length; */
|
|
block.buffer = doc->content_buffer;
|
|
|
|
if (!doc->content_buffer) { /* probably externally viewed image */
|
|
doc->state = DOC_EXTERNAL;
|
|
return NULL;
|
|
/* return DefaultImage(image); */
|
|
}
|
|
|
|
Announce("Processing image %s...", doc->url);
|
|
|
|
if (a == gif_atom)
|
|
{
|
|
if ((data = (char *)LoadGifImage(image, &block, depth)) == NULL)
|
|
{
|
|
Warn("Failed to load GIF image: %s", doc->url);
|
|
Free(block.buffer);
|
|
/* return DefaultImage(image); */
|
|
doc->state = DOC_REJECTED;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
else if (a == xpm_atom)
|
|
{
|
|
if ((data = LoadXpmImage(image, &block, depth)) == NULL)
|
|
{
|
|
Warn("Failed to load XPM image: %s", doc->url);
|
|
Free(block.buffer);
|
|
doc->state = DOC_REJECTED;
|
|
/* return DefaultImage(image); */
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
else if (a == xbm_atom)
|
|
{
|
|
if ((data = LoadXbmImage(image, &block, depth)) == NULL)
|
|
{
|
|
Warn("Failed to load XBM image: %s", doc->url);
|
|
Free(block.buffer);
|
|
doc->state = DOC_REJECTED;
|
|
/* return DefaultImage(image); */
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
#ifdef JPEG
|
|
else if (a == jpeg_atom)
|
|
{
|
|
if ((data = LoadJPEGImage(image, &block, depth)) == NULL)
|
|
{
|
|
Warn("Failed to load JPEG image: %s", doc->url);
|
|
Free(block.buffer);
|
|
doc->state = DOC_REJECTED;
|
|
return NULL;
|
|
}
|
|
}
|
|
#endif /* JPEG */
|
|
|
|
|
|
#ifdef PNG
|
|
else if (a == png_atom || a == png_exp_atom)
|
|
{
|
|
if ((data = LoadPNGImage(image, &block, depth)) == NULL)
|
|
{
|
|
Warn("Failed to load PNG image: %s", doc->url);
|
|
Free(block.buffer);
|
|
doc->state = DOC_REJECTED;
|
|
return NULL;
|
|
}
|
|
}
|
|
#endif /* PNG */
|
|
|
|
else
|
|
{
|
|
Warn("Failed to load unknown image format: %s", doc->url);
|
|
Free(block.buffer);
|
|
doc->state = DOC_REJECTED;
|
|
/* return DefaultImage(image); */
|
|
return NULL;
|
|
}
|
|
|
|
Free(block.buffer);
|
|
doc->state = DOC_PROCESSED;
|
|
doc->content_buffer = NULL; /* howcome 4/12/94: no need to keep the gif source around */
|
|
width = image->width;
|
|
height = image->height;
|
|
|
|
if ((ximage = XCreateImage(display, DefaultVisual(display, screen),
|
|
depth, ZPixmap, 0, data, width, height,
|
|
(depth == 24 ? 32 :(depth == 16 ? 16 : 8)), 0)) == 0)
|
|
{
|
|
Warn("Failed to create XImage: %s", doc->url);
|
|
doc->state = DOC_REJECTED;
|
|
Free(data);
|
|
/* return DefaultImage(image);*/
|
|
return NULL;
|
|
}
|
|
|
|
/* howcome 22/2/95: do we need to set these?? */
|
|
|
|
ximage->byte_order = MSBFirst;
|
|
ximage->bitmap_bit_order = BitmapBitOrder(display);
|
|
|
|
if ((pixmap = XCreatePixmap(display, win, width, height, depth)) == 0)
|
|
{
|
|
Warn("Failed to create Pixmap: %s", doc->url);
|
|
XDestroyImage(ximage); /* also free's image data */
|
|
doc->state = DOC_REJECTED;
|
|
/* return DefaultImage(image); */
|
|
return NULL;
|
|
}
|
|
|
|
drawGC = XCreateGC(display, pixmap, 0, 0);
|
|
XSetFunction(display, drawGC, GXcopy);
|
|
XPutImage(display, pixmap, drawGC, ximage, 0, 0, 0, 0, width, height);
|
|
XFreeGC(display, drawGC);
|
|
XDestroyImage(ximage); /* also free's image data */
|
|
|
|
image->pixmap = pixmap;
|
|
image->width = width;
|
|
image->height = height;
|
|
doc->image = image;
|
|
return doc->image;
|
|
}
|
|
|
|
|
|
Image *GetImage(char *href, int hreflen, BOOL reload)
|
|
{
|
|
Doc *doc = NULL;
|
|
|
|
/* check for null name */
|
|
|
|
if ((doc = GetInline(href, hreflen, reload))) {
|
|
if (doc->image)
|
|
return (doc->image);
|
|
else
|
|
return (ProcessLoadedImage(doc));
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
void FreeImages(int cloned)
|
|
{
|
|
Image *im;
|
|
|
|
while (images)
|
|
{
|
|
/* deallocate colors */
|
|
|
|
if (!cloned && images->npixels > 0)
|
|
XFreeColors(display, colormap, images->pixels, images->npixels, 0);
|
|
|
|
/* free pixmap and image structure */
|
|
|
|
if (!cloned && images->pixmap != default_pixmap)
|
|
XFreePixmap(display, images->pixmap);
|
|
|
|
im = images;
|
|
images = im->next;
|
|
Free(im->url);
|
|
|
|
if (im->npixels > 0)
|
|
Free(im->pixels);
|
|
|
|
Free(im);
|
|
}
|
|
}
|