You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2500 lines
55 KiB
2500 lines
55 KiB
#define _GNU_SOURCE
|
|
#include <config.h>
|
|
#include "Imlib.h"
|
|
#include "Imlib_private.h"
|
|
|
|
#ifdef __EMX__
|
|
#include <io.h>
|
|
#include <process.h>
|
|
#endif
|
|
|
|
#ifndef HAVE_SNPRINTF
|
|
#define snprintf my_snprintf
|
|
#ifdef HAVE_STDARGS
|
|
int my_snprintf(char *str, size_t count, const char *fmt,...);
|
|
|
|
#else
|
|
int my_snprintf(va_alist);
|
|
|
|
#endif
|
|
#endif
|
|
|
|
void
|
|
calc_map_tables(ImlibData * id, ImlibImage * im)
|
|
{
|
|
int i;
|
|
double g, b, c, ii, v;
|
|
|
|
if (!im)
|
|
return;
|
|
|
|
g = ((double)im->mod.gamma) / 256;
|
|
b = ((double)im->mod.brightness) / 256;
|
|
c = ((double)im->mod.contrast) / 256;
|
|
if (g < 0.01)
|
|
g = 0.01;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
ii = ((double)i) / 256;
|
|
v = ((ii - 0.5) * c) + 0.5 + (b - 1);
|
|
if (v > 0)
|
|
v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
|
|
else
|
|
v = 0;
|
|
if (v > 255)
|
|
v = 255;
|
|
else if (v < 0)
|
|
v = 0;
|
|
im->rmap[i] = (unsigned char)v;
|
|
im->gmap[i] = (unsigned char)v;
|
|
im->bmap[i] = (unsigned char)v;
|
|
}
|
|
g = ((double)im->rmod.gamma) / 256;
|
|
b = ((double)im->rmod.brightness) / 256;
|
|
c = ((double)im->rmod.contrast) / 256;
|
|
if (g < 0.01)
|
|
g = 0.01;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
ii = ((double)im->rmap[i]) / 256;
|
|
v = ((ii - 0.5) * c) + 0.5 + (b - 1);
|
|
if (v > 0)
|
|
v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
|
|
else
|
|
v = 0;
|
|
if (v > 255)
|
|
v = 255;
|
|
else if (v < 0)
|
|
v = 0;
|
|
im->rmap[i] = (unsigned char)v;
|
|
}
|
|
g = ((double)im->gmod.gamma) / 256;
|
|
b = ((double)im->gmod.brightness) / 256;
|
|
c = ((double)im->gmod.contrast) / 256;
|
|
if (g < 0.01)
|
|
g = 0.01;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
ii = ((double)im->gmap[i]) / 256;
|
|
v = ((ii - 0.5) * c) + 0.5 + (b - 1);
|
|
if (v > 0)
|
|
v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
|
|
else
|
|
v = 0;
|
|
if (v > 255)
|
|
v = 255;
|
|
else if (v < 0)
|
|
v = 0;
|
|
im->gmap[i] = (unsigned char)v;
|
|
}
|
|
g = ((double)im->bmod.gamma) / 256;
|
|
b = ((double)im->bmod.brightness) / 256;
|
|
c = ((double)im->bmod.contrast) / 256;
|
|
if (g < 0.01)
|
|
g = 0.01;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
ii = ((double)im->bmap[i]) / 256;
|
|
v = ((ii - 0.5) * c) + 0.5 + (b - 1);
|
|
if (v > 0)
|
|
v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
|
|
else
|
|
v = 0;
|
|
if (v > 255)
|
|
v = 255;
|
|
else if (v < 0)
|
|
v = 0;
|
|
im->bmap[i] = (unsigned char)v;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
|
|
int
|
|
Imlib_load_file_to_pixmap(ImlibData * id, char *filename, Pixmap * pmap, Pixmap * mask)
|
|
{
|
|
ImlibImage *im;
|
|
|
|
im = Imlib_load_image(id, filename);
|
|
if (!im)
|
|
{
|
|
if (pmap)
|
|
*pmap = 0;
|
|
if (mask)
|
|
*mask = 0;
|
|
return 0;
|
|
}
|
|
if (!Imlib_render(id, im, im->rgb_width, im->rgb_height))
|
|
{
|
|
Imlib_destroy_image(id, im);
|
|
if (pmap)
|
|
*pmap = 0;
|
|
if (mask)
|
|
*mask = 0;
|
|
return 0;
|
|
}
|
|
if (pmap)
|
|
*pmap = Imlib_move_image(id, im);
|
|
if (mask)
|
|
*mask = Imlib_move_mask(id, im);
|
|
Imlib_destroy_image(id, im);
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_modifier(ImlibData * id, ImlibImage * im, ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
if ((im->mod.gamma != mod->gamma) || (im->mod.brightness != mod->brightness) || (im->mod.contrast != mod->contrast))
|
|
{
|
|
im->mod.gamma = mod->gamma;
|
|
im->mod.brightness = mod->brightness;
|
|
im->mod.contrast = mod->contrast;
|
|
calc_map_tables(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_red_modifier(ImlibData * id, ImlibImage * im,
|
|
ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
if ((im->rmod.gamma != mod->gamma) ||
|
|
(im->rmod.brightness != mod->brightness) ||
|
|
(im->rmod.contrast != mod->contrast))
|
|
{
|
|
im->rmod.gamma = mod->gamma;
|
|
im->rmod.brightness = mod->brightness;
|
|
im->rmod.contrast = mod->contrast;
|
|
calc_map_tables(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_green_modifier(ImlibData * id, ImlibImage * im,
|
|
ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
if ((im->gmod.gamma != mod->gamma) ||
|
|
(im->gmod.brightness != mod->brightness) ||
|
|
(im->gmod.contrast != mod->contrast))
|
|
{
|
|
im->gmod.gamma = mod->gamma;
|
|
im->gmod.brightness = mod->brightness;
|
|
im->gmod.contrast = mod->contrast;
|
|
calc_map_tables(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_blue_modifier(ImlibData * id, ImlibImage * im,
|
|
ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
if ((im->bmod.gamma != mod->gamma) ||
|
|
(im->bmod.brightness != mod->brightness) ||
|
|
(im->bmod.contrast != mod->contrast))
|
|
{
|
|
im->bmod.gamma = mod->gamma;
|
|
im->bmod.brightness = mod->brightness;
|
|
im->bmod.contrast = mod->contrast;
|
|
calc_map_tables(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_modifier(ImlibData * id, ImlibImage * im,
|
|
ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
mod->gamma = im->mod.gamma;
|
|
mod->brightness = im->mod.brightness;
|
|
mod->contrast = im->mod.contrast;
|
|
calc_map_tables(id, im);
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_red_modifier(ImlibData * id, ImlibImage * im, ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
mod->gamma = im->rmod.gamma;
|
|
mod->brightness = im->rmod.brightness;
|
|
mod->contrast = im->rmod.contrast;
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_green_modifier(ImlibData * id, ImlibImage * im, ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
mod->gamma = im->gmod.gamma;
|
|
mod->brightness = im->gmod.brightness;
|
|
mod->contrast = im->gmod.contrast;
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_blue_modifier(ImlibData * id, ImlibImage * im, ImlibColorModifier * mod)
|
|
{
|
|
if ((!im) | (!mod))
|
|
return;
|
|
mod->gamma = im->bmod.gamma;
|
|
mod->brightness = im->bmod.brightness;
|
|
mod->contrast = im->bmod.contrast;
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_red_curve(ImlibData * id, ImlibImage * im, unsigned char *mod)
|
|
{
|
|
int i;
|
|
char same = 1;
|
|
|
|
if ((!im) || (!mod))
|
|
return;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
if (im->rmap[i] != mod[i])
|
|
{
|
|
same = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (same)
|
|
return;
|
|
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
|
|
for (i = 0; i < 256; i++)
|
|
im->rmap[i] = mod[i];
|
|
|
|
im->mod.contrast = 257;
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_green_curve(ImlibData * id, ImlibImage * im, unsigned char *mod)
|
|
{
|
|
int i;
|
|
char same = 1;
|
|
|
|
if ((!im) || (!mod))
|
|
return;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
if (im->gmap[i] != mod[i])
|
|
{
|
|
same = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (same)
|
|
return;
|
|
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
for (i = 0; i < 256; i++)
|
|
im->gmap[i] = mod[i];
|
|
|
|
im->mod.contrast = 257;
|
|
}
|
|
|
|
void
|
|
Imlib_set_image_blue_curve(ImlibData * id, ImlibImage * im, unsigned char *mod)
|
|
{
|
|
int i;
|
|
char same = 1;
|
|
|
|
if ((!im) || (!mod))
|
|
return;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
if (im->bmap[i] != mod[i])
|
|
{
|
|
same = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (same)
|
|
return;
|
|
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
for (i = 0; i < 256; i++)
|
|
im->bmap[i] = mod[i];
|
|
|
|
im->mod.contrast = 257;
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_red_curve(ImlibData * id, ImlibImage * im, unsigned char *mod)
|
|
{
|
|
int i;
|
|
|
|
if ((!im) || (!mod))
|
|
return;
|
|
for (i = 0; i < 256; i++)
|
|
mod[i] = im->rmap[i];
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_green_curve(ImlibData * id, ImlibImage * im, unsigned char *mod)
|
|
{
|
|
int i;
|
|
|
|
if ((!im) || (!mod))
|
|
return;
|
|
for (i = 0; i < 256; i++)
|
|
mod[i] = im->gmap[i];
|
|
}
|
|
|
|
void
|
|
Imlib_get_image_blue_curve(ImlibData * id, ImlibImage * im, unsigned char *mod)
|
|
{
|
|
int i;
|
|
|
|
if ((!im) || (!mod))
|
|
return;
|
|
for (i = 0; i < 256; i++)
|
|
mod[i] = im->bmap[i];
|
|
}
|
|
|
|
void
|
|
Imlib_apply_modifiers_to_rgb(ImlibData * id, ImlibImage * im)
|
|
{
|
|
int x, y;
|
|
unsigned char *ptr;
|
|
|
|
if (!im)
|
|
return;
|
|
ptr = im->rgb_data;
|
|
for (y = 0; y < im->rgb_height; y++)
|
|
{
|
|
for (x = 0; x < im->rgb_width; x++)
|
|
{
|
|
*ptr = im->rmap[*ptr];
|
|
ptr++;
|
|
*ptr = im->gmap[*ptr];
|
|
ptr++;
|
|
*ptr = im->bmap[*ptr];
|
|
ptr++;
|
|
}
|
|
}
|
|
im->mod.gamma = 256;
|
|
im->mod.brightness = 256;
|
|
im->mod.contrast = 256;
|
|
im->rmod.gamma = 256;
|
|
im->rmod.brightness = 256;
|
|
im->rmod.contrast = 256;
|
|
im->gmod.gamma = 256;
|
|
im->gmod.brightness = 256;
|
|
im->gmod.contrast = 256;
|
|
im->bmod.gamma = 256;
|
|
im->bmod.brightness = 256;
|
|
im->bmod.contrast = 256;
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
calc_map_tables(id, im);
|
|
dirty_images(id, im);
|
|
}
|
|
|
|
#define SHADE_PIXEL(pixel, dir, tmp) do {(tmp) = ((((double)pixel)/256.0) +\
|
|
((dir) ? 0.2 : -0.2)) * 256.0; \
|
|
if ((tmp) > 255) (tmp) = 255; else if ((tmp) < 0) (tmp) = 0;} while (0)
|
|
|
|
void
|
|
Imlib_bevel_image(ImlibData *id, ImlibImage *im, ImlibBorder *bord,
|
|
unsigned char up)
|
|
{
|
|
register unsigned char *ptr;
|
|
double v;
|
|
int x, y, xbound, ybound;
|
|
|
|
if ((!im) || (!bord))
|
|
return;
|
|
|
|
/* Left edge */
|
|
ptr = im->rgb_data + 3 * im->rgb_width * bord->top;
|
|
for (y = bord->top; y < im->rgb_height; y++)
|
|
{
|
|
xbound = im->rgb_height - y;
|
|
if (xbound > bord->left)
|
|
xbound = bord->left;
|
|
for (x = 0; x < xbound; x++)
|
|
{
|
|
SHADE_PIXEL(*ptr, up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
}
|
|
ptr += 3 * (im->rgb_width - xbound);
|
|
}
|
|
|
|
/* Right edge */
|
|
ybound = im->rgb_height - bord->bottom;
|
|
for (ptr = im->rgb_data, y = 0; y < ybound; y++)
|
|
{
|
|
xbound = bord->right - y;
|
|
if (xbound < 0)
|
|
xbound = 0;
|
|
ptr += 3 * (im->rgb_width - bord->right + xbound);
|
|
for (x = xbound; x < bord->right; x++)
|
|
{
|
|
SHADE_PIXEL(*ptr, !up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, !up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, !up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
}
|
|
}
|
|
|
|
/* Top edge */
|
|
ptr = im->rgb_data;
|
|
for (y = 0; y < bord->top; y++)
|
|
{
|
|
xbound = im->rgb_width - y;
|
|
for (x = 0; x < xbound; x++)
|
|
{
|
|
SHADE_PIXEL(*ptr, up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
}
|
|
ptr += y * 3;
|
|
}
|
|
|
|
/* Bottom edge */
|
|
ptr = im->rgb_data + ((im->rgb_height - bord->bottom) * im->rgb_width * 3);
|
|
for (y = bord->bottom - 1; y >= 0; y--)
|
|
{
|
|
ptr += y * 3;
|
|
for (x = y; x < im->rgb_width; x++)
|
|
{
|
|
SHADE_PIXEL(*ptr, !up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, !up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
SHADE_PIXEL(*ptr, !up, v);
|
|
*ptr++ = (unsigned char) v;
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef SHADE_PIXEL
|
|
#define SHADE_PIXEL(pixel, dir, tmp) do {(tmp) = ((((double)pixel)/depth_factor) + ((dir) ? 0.2 : -0.2)) * depth_factor; \
|
|
if ((tmp) > (depth_factor-1)) (tmp) = depth_factor - 1; else if ((tmp) < 0) (tmp) = 0;} while (0)
|
|
#define MOD_PIXEL_LOW(x, y, up) do {v = XGetPixel(ximg, (x), (y)); r = (int) ctab[v & 0xff].r; g = (int) ctab[v & 0xff].g; b = (int) ctab[v & 0xff].b; \
|
|
SHADE_PIXEL(r, (up), dv); r = (int) dv; SHADE_PIXEL(g, (up), dv); g = (int) dv; SHADE_PIXEL(b, (up), dv); b = (int) dv; \
|
|
v = Imlib_best_color_match(id, &r, &g, &b); XPutPixel(ximg, (x), (y), v);} while (0)
|
|
#define MOD_PIXEL_HIGH(x, y, up) do {v = XGetPixel(ximg, (x), (y)); r = (int) ((v >> br) & mr); g = (int) ((v >> bg) & mg); b = (int) ((v << bb) & mb); \
|
|
SHADE_PIXEL(r, (up), dv); r = (int) dv; SHADE_PIXEL(g, (up), dv); g = (int) dv; SHADE_PIXEL(b, (up), dv); b = (int) dv; \
|
|
v = ((r & mr) << br) | ((g & mg) << bg) | ((b & mb) >> bb); XPutPixel(ximg, (x), (y), v);} while (0)
|
|
|
|
void
|
|
Imlib_bevel_pixmap(ImlibData *id, Pixmap p, int w, int h, ImlibBorder *bord, unsigned char up)
|
|
{
|
|
|
|
XImage *ximg;
|
|
register unsigned long i, v;
|
|
double dv;
|
|
short x, y, xbound, ybound;
|
|
unsigned int r, g, b;
|
|
ImlibColor ctab[256];
|
|
int real_depth = 0, depth_factor;
|
|
register int br, bg, bb; /* Bitshifts */
|
|
register unsigned int mr, mg, mb; /* Bitmasks */
|
|
XGCValues gcv;
|
|
GC gc;
|
|
|
|
if ((!id) || (!bord))
|
|
return;
|
|
|
|
depth_factor = 1 << id->x.depth;
|
|
if (id->x.depth <= 8) {
|
|
|
|
XColor cols[256];
|
|
|
|
for (i = 0; i < depth_factor; i++) {
|
|
cols[i].pixel = i;
|
|
cols[i].flags = DoRed | DoGreen | DoBlue;
|
|
}
|
|
XQueryColors(id->x.disp, id->x.root_cmap, cols, depth_factor);
|
|
for (i = 0; i < depth_factor; i++) {
|
|
ctab[i].r = cols[i].red >> 8;
|
|
ctab[i].g = cols[i].green >> 8;
|
|
ctab[i].b = cols[i].blue >> 8;
|
|
ctab[i].pixel = cols[i].pixel;
|
|
}
|
|
} else if (id->x.depth == 16) {
|
|
|
|
XWindowAttributes xattr;
|
|
|
|
XGetWindowAttributes(id->x.disp, id->x.root, &xattr);
|
|
if ((xattr.visual->red_mask == 0x7c00) && (xattr.visual->green_mask == 0x3e0) && (xattr.visual->blue_mask == 0x1f)) {
|
|
real_depth = 15;
|
|
depth_factor = 1 << 15;
|
|
}
|
|
}
|
|
if (!real_depth) {
|
|
real_depth = id->x.depth;
|
|
}
|
|
ximg = XGetImage(id->x.disp, p, 0, 0, w, h, -1, ZPixmap);
|
|
if (ximg == NULL) {
|
|
return;
|
|
}
|
|
if (id->x.depth <= 8) {
|
|
/* Left edge */
|
|
for (y = bord->top; y < h; y++)
|
|
{
|
|
xbound = h - y;
|
|
if (xbound > bord->left)
|
|
xbound = bord->left;
|
|
for (x = 0; x < xbound; x++)
|
|
{
|
|
MOD_PIXEL_LOW(x, y, up);
|
|
}
|
|
}
|
|
|
|
/* Right edge */
|
|
ybound = h - bord->bottom;
|
|
for (y = 0; y < ybound; y++)
|
|
{
|
|
xbound = bord->right - y;
|
|
if (xbound < 0)
|
|
xbound = 0;
|
|
for (x = xbound; x < bord->right; x++)
|
|
{
|
|
MOD_PIXEL_LOW(x + (w - bord->right), y, !up);
|
|
}
|
|
}
|
|
|
|
/* Top edge */
|
|
for (y = 0; y < bord->top; y++)
|
|
{
|
|
xbound = w - y;
|
|
for (x = 0; x < xbound; x++)
|
|
{
|
|
MOD_PIXEL_LOW(x, y, up);
|
|
}
|
|
}
|
|
|
|
/* Bottom edge */
|
|
for (y = h - bord->bottom; y < h; y++)
|
|
{
|
|
for (x = h - y - 1; x < w; x++)
|
|
{
|
|
MOD_PIXEL_LOW(x, y, !up);
|
|
}
|
|
}
|
|
} else {
|
|
/* Determine bitshift and bitmask values */
|
|
switch (real_depth) {
|
|
case 15:
|
|
br = 7;
|
|
bg = 2;
|
|
bb = 3;
|
|
mr = mg = mb = 0xf8;
|
|
break;
|
|
case 16:
|
|
br = 8;
|
|
bg = bb = 3;
|
|
mr = mb = 0xf8;
|
|
mg = 0xfc;
|
|
break;
|
|
case 24:
|
|
case 32:
|
|
br = 16;
|
|
bg = 8;
|
|
bb = 0;
|
|
mr = mg = mb = 0xff;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
/* Left edge */
|
|
for (y = bord->top; y < h; y++)
|
|
{
|
|
xbound = h - y;
|
|
if (xbound > bord->left)
|
|
xbound = bord->left;
|
|
for (x = 0; x < xbound; x++)
|
|
{
|
|
MOD_PIXEL_HIGH(x, y, up);
|
|
}
|
|
}
|
|
|
|
/* Right edge */
|
|
ybound = h - bord->bottom;
|
|
for (y = 0; y < ybound; y++)
|
|
{
|
|
xbound = bord->right - y;
|
|
if (xbound < 0)
|
|
xbound = 0;
|
|
for (x = xbound; x < bord->right; x++)
|
|
{
|
|
MOD_PIXEL_HIGH(x + (w - bord->right), y, !up);
|
|
}
|
|
}
|
|
|
|
/* Top edge */
|
|
for (y = 0; y < bord->top; y++)
|
|
{
|
|
xbound = w - y;
|
|
for (x = 0; x < xbound; x++)
|
|
{
|
|
MOD_PIXEL_HIGH(x, y, up);
|
|
}
|
|
}
|
|
|
|
/* Bottom edge */
|
|
for (y = h - bord->bottom; y < h; y++)
|
|
{
|
|
for (x = h - y - 1; x < w; x++)
|
|
{
|
|
MOD_PIXEL_HIGH(x, y, !up);
|
|
}
|
|
}
|
|
}
|
|
gc = XCreateGC(id->x.disp, p, 0, &gcv);
|
|
XPutImage(id->x.disp, p, gc, ximg, 0, 0, 0, 0, w, h);
|
|
XFreeGC(id->x.disp, gc);
|
|
XDestroyImage(ximg);
|
|
}
|
|
|
|
void
|
|
Imlib_crop_image(ImlibData * id, ImlibImage * im, int x, int y, int w, int h)
|
|
{
|
|
unsigned char *data;
|
|
int xx, yy, w3, w4;
|
|
unsigned char *ptr1, *ptr2;
|
|
|
|
if (!im)
|
|
return;
|
|
if (x < 0)
|
|
{
|
|
w += x;
|
|
x = 0;
|
|
}
|
|
if (y < 0)
|
|
{
|
|
h += y;
|
|
y = 0;
|
|
}
|
|
if (x >= im->rgb_width)
|
|
return;
|
|
if (y >= im->rgb_height)
|
|
return;
|
|
if (w <= 0)
|
|
return;
|
|
if (h <= 0)
|
|
return;
|
|
if (x + w > im->rgb_width)
|
|
w = im->rgb_width - x;
|
|
if (y + h > im->rgb_height)
|
|
h = im->rgb_height - y;
|
|
if (w <= 0)
|
|
return;
|
|
if (h <= 0)
|
|
return;
|
|
|
|
w3 = im->rgb_width * 3;
|
|
w4 = (im->rgb_width - w) * 3;
|
|
data = _imlib_malloc_image(w, h);
|
|
if (data == NULL)
|
|
return;
|
|
ptr1 = im->rgb_data + (y * w3) + (x * 3);
|
|
ptr2 = data;
|
|
for (yy = 0; yy < h; yy++)
|
|
{
|
|
for (xx = 0; xx < w; xx++)
|
|
{
|
|
*ptr2++ = *ptr1++;
|
|
*ptr2++ = *ptr1++;
|
|
*ptr2++ = *ptr1++;
|
|
}
|
|
ptr1 += w4;
|
|
}
|
|
free(im->rgb_data);
|
|
im->rgb_data = data;
|
|
if (im->border.left > x)
|
|
im->border.left = im->border.left - x;
|
|
else
|
|
im->border.left = 0;
|
|
if (im->border.top > y)
|
|
im->border.top = im->border.top - y;
|
|
else
|
|
im->border.top = 0;
|
|
if (im->rgb_width - im->border.right < x + w)
|
|
im->border.right = im->border.right - (im->rgb_width - (x + w));
|
|
else
|
|
im->border.right = 0;
|
|
if (im->rgb_height - im->border.bottom < y + h)
|
|
im->border.bottom = im->border.bottom - (im->rgb_height - (y + h));
|
|
else
|
|
im->border.bottom = 0;
|
|
im->rgb_width = w;
|
|
im->rgb_height = h;
|
|
dirty_images(id, im);
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_crop_and_clone_image(ImlibData * id, ImlibImage * im, int x, int y, int w, int h)
|
|
{
|
|
unsigned char *data;
|
|
int xx, yy, w3, w4;
|
|
unsigned char *ptr1, *ptr2;
|
|
ImlibImage *im2;
|
|
char *s;
|
|
|
|
if (!im)
|
|
return NULL;
|
|
im2 = malloc(sizeof(ImlibImage));
|
|
if (!im2)
|
|
return NULL;
|
|
|
|
if (x < 0)
|
|
{
|
|
w += x;
|
|
x = 0;
|
|
}
|
|
if (y < 0)
|
|
{
|
|
h += y;
|
|
y = 0;
|
|
}
|
|
if (x >= im->rgb_width)
|
|
return NULL;
|
|
if (y >= im->rgb_height)
|
|
return NULL;
|
|
if (w <= 0)
|
|
return NULL;
|
|
if (h <= 0)
|
|
return NULL;
|
|
if (x + w > im->rgb_width)
|
|
w = im->rgb_width - x;
|
|
if (y + h > im->rgb_height)
|
|
h = im->rgb_height - y;
|
|
if (w <= 0)
|
|
return NULL;
|
|
if (h <= 0)
|
|
return NULL;
|
|
|
|
w3 = im->rgb_width * 3;
|
|
w4 = (im->rgb_width - w) * 3;
|
|
data = _imlib_malloc_image(w, h);
|
|
if (data == NULL)
|
|
return NULL;
|
|
ptr1 = im->rgb_data + (y * w3) + (x * 3);
|
|
ptr2 = data;
|
|
for (yy = 0; yy < h; yy++)
|
|
{
|
|
for (xx = 0; xx < w; xx++)
|
|
{
|
|
*ptr2++ = *ptr1++;
|
|
*ptr2++ = *ptr1++;
|
|
*ptr2++ = *ptr1++;
|
|
}
|
|
ptr1 += w4;
|
|
}
|
|
if (im->border.left > x)
|
|
im2->border.left = im->border.left - x;
|
|
else
|
|
im2->border.left = 0;
|
|
if (im->border.top > y)
|
|
im2->border.top = im->border.top - y;
|
|
else
|
|
im2->border.top = 0;
|
|
if (im->rgb_width - im->border.right < x + w)
|
|
im2->border.right = im->border.right - (im->rgb_width - (x + w));
|
|
else
|
|
im2->border.right = 0;
|
|
if (im->rgb_height - im->border.bottom < y + h)
|
|
im2->border.bottom = im->border.bottom - (im->rgb_height - (y + h));
|
|
else
|
|
im2->border.bottom = 0;
|
|
im2->rgb_data = data;
|
|
im2->rgb_width = w;
|
|
im2->rgb_height = h;
|
|
im2->alpha_data = NULL;
|
|
s = malloc(strlen(im->filename) + 320);
|
|
if (s)
|
|
{
|
|
snprintf(s, sizeof(s), "%s_%x_%x", im->filename, (int)time(NULL), (int)rand());
|
|
im2->filename = malloc(strlen(s) + 1);
|
|
if (im2->filename)
|
|
strcpy(im2->filename, s);
|
|
free(s);
|
|
}
|
|
else
|
|
im2->filename = NULL;
|
|
im2->width = 0;
|
|
im2->height = 0;
|
|
im2->shape_color.r = im->shape_color.r;
|
|
im2->shape_color.g = im->shape_color.g;
|
|
im2->shape_color.b = im->shape_color.b;
|
|
im2->pixmap = 0;
|
|
im2->shape_mask = 0;
|
|
im2->cache = 1;
|
|
im2->mod.gamma = im->mod.gamma;
|
|
im2->mod.brightness = im->mod.brightness;
|
|
im2->mod.contrast = im->mod.contrast;
|
|
im2->rmod.gamma = im->rmod.gamma;
|
|
im2->rmod.brightness = im->rmod.brightness;
|
|
im2->rmod.contrast = im->rmod.contrast;
|
|
im2->gmod.gamma = im->gmod.gamma;
|
|
im2->gmod.brightness = im->gmod.brightness;
|
|
im2->gmod.contrast = im->gmod.contrast;
|
|
im2->bmod.gamma = im->bmod.gamma;
|
|
im2->bmod.brightness = im->bmod.brightness;
|
|
im2->bmod.contrast = im->bmod.contrast;
|
|
calc_map_tables(id, im2);
|
|
if (id->cache.on_image)
|
|
add_image(id, im2, im2->filename);
|
|
return im2;
|
|
}
|
|
|
|
void
|
|
Imlib_changed_image(ImlibData * id, ImlibImage * im)
|
|
{
|
|
if (!im)
|
|
return;
|
|
dirty_images(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
|
|
void
|
|
Imlib_apply_image(ImlibData * id, ImlibImage * im, Window p)
|
|
{
|
|
Pixmap pp, mm;
|
|
int x, y;
|
|
unsigned int w, h, bd, d;
|
|
Window ww;
|
|
|
|
if ((!im) || (!p))
|
|
return;
|
|
XGetGeometry(id->x.disp, p, &ww, &x, &y, &w, &h, &bd, &d);
|
|
if ((w <= 0) || (h <= 0))
|
|
return;
|
|
Imlib_render(id, im, w, h);
|
|
pp = Imlib_move_image(id, im);
|
|
mm = Imlib_move_mask(id, im);
|
|
XSetWindowBackgroundPixmap(id->x.disp, p, pp);
|
|
if (mm)
|
|
XShapeCombineMask(id->x.disp, p, ShapeBounding, 0, 0, mm, ShapeSet);
|
|
else
|
|
XShapeCombineMask(id->x.disp, p, ShapeBounding, 0, 0, 0, ShapeSet);
|
|
XClearWindow(id->x.disp, p);
|
|
Imlib_free_pixmap(id, pp);
|
|
}
|
|
|
|
void
|
|
Imlib_paste_image(ImlibData * id, ImlibImage * im, Window p, int x, int y, int w, int h)
|
|
{
|
|
GC gc;
|
|
XGCValues gcv;
|
|
Pixmap pp, mm;
|
|
|
|
if ((!im) || (!p))
|
|
return;
|
|
if ((w <= 0) || (h <= 0))
|
|
return;
|
|
gc = XCreateGC(id->x.disp, p, 0, &gcv);
|
|
Imlib_render(id, im, w, h);
|
|
pp = Imlib_move_image(id, im);
|
|
mm = Imlib_move_mask(id, im);
|
|
if (mm)
|
|
{
|
|
XSetClipMask(id->x.disp, gc, mm);
|
|
XSetClipOrigin(id->x.disp, gc, x, y);
|
|
}
|
|
XCopyArea(id->x.disp, pp, p, gc, 0, 0, w, h, x, y);
|
|
Imlib_free_pixmap(id, pp);
|
|
XFreeGC(id->x.disp, gc);
|
|
}
|
|
|
|
void
|
|
Imlib_paste_image_border(ImlibData * id, ImlibImage * im, Window p, int x, int y, int w, int h)
|
|
{
|
|
GC gc;
|
|
XGCValues gcv;
|
|
Pixmap pp, mm;
|
|
|
|
if (!im)
|
|
return;
|
|
if ((w <= 0) || (h <= 0))
|
|
return;
|
|
gc = XCreateGC(id->x.disp, p, 0, &gcv);
|
|
Imlib_render(id, im, w, h);
|
|
pp = Imlib_move_image(id, im);
|
|
mm = Imlib_move_mask(id, im);
|
|
if (mm)
|
|
{
|
|
XSetClipMask(id->x.disp, gc, mm);
|
|
XSetClipOrigin(id->x.disp, gc, x, y);
|
|
}
|
|
if ((w <= (im->border.left + im->border.right)) ||
|
|
(h <= (im->border.top + im->border.bottom)))
|
|
XCopyArea(id->x.disp, pp, p, gc, 0, 0, w, h, x, y);
|
|
else
|
|
{
|
|
XCopyArea(id->x.disp, pp, p, gc,
|
|
0, 0,
|
|
x, y,
|
|
w, im->border.top);
|
|
XCopyArea(id->x.disp, pp, p, gc,
|
|
0, h - im->border.bottom,
|
|
x, y + (h - im->border.bottom),
|
|
w, im->border.bottom);
|
|
XCopyArea(id->x.disp, pp, p, gc,
|
|
0, im->border.top,
|
|
x, y + im->border.top,
|
|
im->border.left, h - (im->border.top + im->border.bottom));
|
|
XCopyArea(id->x.disp, pp, p, gc,
|
|
w - im->border.right, im->border.top,
|
|
x + (w - im->border.right), y + im->border.top,
|
|
im->border.right, h - (im->border.top + im->border.bottom));
|
|
}
|
|
Imlib_free_pixmap(id, pp);
|
|
XFreeGC(id->x.disp, gc);
|
|
}
|
|
|
|
void
|
|
Imlib_flip_image_horizontal(ImlibData * id, ImlibImage * im)
|
|
{
|
|
unsigned char *ptr1, *ptr2, r, rr;
|
|
int x, y;
|
|
int w3;
|
|
|
|
if (!im)
|
|
return;
|
|
w3 = im->rgb_width * 3;
|
|
for (y = 0; y < im->rgb_height; y++)
|
|
{
|
|
ptr1 = im->rgb_data + (y * w3);
|
|
ptr2 = im->rgb_data + (y * w3) + w3 - 3;
|
|
for (x = 0; x < im->rgb_width >> 1; x++)
|
|
{
|
|
r = *ptr1;
|
|
rr = *ptr2;
|
|
*ptr2++ = r;
|
|
*ptr1++ = rr;
|
|
r = *ptr1;
|
|
rr = *ptr2;
|
|
*ptr2++ = r;
|
|
*ptr1++ = rr;
|
|
r = *ptr1;
|
|
rr = *ptr2;
|
|
*ptr2 = r;
|
|
*ptr1++ = rr;
|
|
ptr2 -= 5;
|
|
}
|
|
}
|
|
w3 = im->border.left;
|
|
im->border.left = im->border.right;
|
|
im->border.right = w3;
|
|
dirty_images(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
|
|
void
|
|
Imlib_flip_image_vertical(ImlibData * id, ImlibImage * im)
|
|
{
|
|
unsigned char *ptr1, *ptr2, r, rr;
|
|
int x, y, yy;
|
|
int w3;
|
|
|
|
if (!im)
|
|
return;
|
|
w3 = im->rgb_width * 3;
|
|
for (yy = im->rgb_height - 1, y = 0; y < im->rgb_height >> 1; y++, yy--)
|
|
{
|
|
ptr1 = im->rgb_data + (y * w3);
|
|
ptr2 = im->rgb_data + (yy * w3);
|
|
for (x = 0; x < im->rgb_width; x++)
|
|
{
|
|
r = *ptr1;
|
|
rr = *ptr2;
|
|
*ptr2++ = r;
|
|
*ptr1++ = rr;
|
|
r = *ptr1;
|
|
rr = *ptr2;
|
|
*ptr2++ = r;
|
|
*ptr1++ = rr;
|
|
r = *ptr1;
|
|
rr = *ptr2;
|
|
*ptr2++ = r;
|
|
*ptr1++ = rr;
|
|
}
|
|
}
|
|
w3 = im->border.top;
|
|
im->border.top = im->border.bottom;
|
|
im->border.bottom = w3;
|
|
dirty_images(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
|
|
void
|
|
Imlib_rotate_image(ImlibData * id, ImlibImage * im, int d)
|
|
{
|
|
unsigned char *data;
|
|
int x, y, w3, w4;
|
|
unsigned char *ptr1, *ptr2;
|
|
|
|
if (!im)
|
|
return;
|
|
w3 = im->rgb_width * 3;
|
|
w4 = im->rgb_height * 3;
|
|
data = _imlib_malloc_image(im->rgb_width, im->rgb_height);
|
|
if (data == NULL)
|
|
return;
|
|
for (y = 0; y < im->rgb_height; y++)
|
|
{
|
|
ptr1 = im->rgb_data + (y * w3);
|
|
ptr2 = data + (y * 3);
|
|
for (x = 0; x < im->rgb_width; x++)
|
|
{
|
|
*ptr2++ = *ptr1++;
|
|
*ptr2++ = *ptr1++;
|
|
*ptr2 = *ptr1++;
|
|
ptr2 += w4 - 2;
|
|
}
|
|
}
|
|
free(im->rgb_data);
|
|
im->rgb_data = data;
|
|
w3 = im->rgb_width;
|
|
im->rgb_width = im->rgb_height;
|
|
im->rgb_height = w3;
|
|
w3 = im->border.top;
|
|
im->border.top = im->border.left;
|
|
im->border.left = w3;
|
|
w3 = im->border.bottom;
|
|
im->border.bottom = im->border.right;
|
|
im->border.right = w3;
|
|
dirty_images(id, im);
|
|
if (im->pixmap)
|
|
{
|
|
free_pixmappmap(id, im->pixmap);
|
|
im->pixmap = 0;
|
|
}
|
|
dirty_pixmaps(id, im);
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_create_image_from_data(ImlibData * id, unsigned char *data, unsigned char *alpha, int w, int h)
|
|
{
|
|
ImlibImage *im;
|
|
char s[1024];
|
|
|
|
if ((!data) || (w <= 0) || (h <= 0))
|
|
return NULL;
|
|
im = malloc(sizeof(ImlibImage));
|
|
if (!im)
|
|
return NULL;
|
|
im->rgb_width = w;
|
|
im->rgb_height = h;
|
|
im->rgb_data = _imlib_malloc_image(im->rgb_width, im->rgb_height);
|
|
if (!im->rgb_data)
|
|
{
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
memcpy(im->rgb_data, data, im->rgb_width * im->rgb_height * 3);
|
|
/* im->alpha_data=alpha; */
|
|
im->alpha_data = NULL;
|
|
snprintf(s, sizeof(s), "creat_%x_%x", (int)time(NULL), (int)rand());
|
|
im->filename = malloc(strlen(s) + 1);
|
|
if (im->filename)
|
|
strcpy(im->filename, s);
|
|
im->width = 0;
|
|
im->height = 0;
|
|
im->shape_color.r = -1;
|
|
im->shape_color.g = -1;
|
|
im->shape_color.b = -1;
|
|
im->border.left = 0;
|
|
im->border.right = 0;
|
|
im->border.top = 0;
|
|
im->border.bottom = 0;
|
|
im->pixmap = 0;
|
|
im->shape_mask = 0;
|
|
im->cache = 1;
|
|
im->mod.gamma = id->mod.gamma;
|
|
im->mod.brightness = id->mod.brightness;
|
|
im->mod.contrast = id->mod.contrast;
|
|
im->rmod.gamma = id->rmod.gamma;
|
|
im->rmod.brightness = id->rmod.brightness;
|
|
im->rmod.contrast = id->rmod.contrast;
|
|
im->gmod.gamma = id->gmod.gamma;
|
|
im->gmod.brightness = id->gmod.brightness;
|
|
im->gmod.contrast = id->gmod.contrast;
|
|
im->bmod.gamma = id->bmod.gamma;
|
|
im->bmod.brightness = id->bmod.brightness;
|
|
im->bmod.contrast = id->bmod.contrast;
|
|
if (id->cache.on_image)
|
|
add_image(id, im, im->filename);
|
|
calc_map_tables(id, im);
|
|
return im;
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_clone_image(ImlibData * id, ImlibImage * im)
|
|
{
|
|
ImlibImage *im2;
|
|
char *s;
|
|
|
|
if (!im)
|
|
return NULL;
|
|
im2 = malloc(sizeof(ImlibImage));
|
|
if (!im2)
|
|
return NULL;
|
|
im2->rgb_width = im->rgb_width;
|
|
im2->rgb_height = im->rgb_height;
|
|
im2->rgb_data = _imlib_malloc_image(im2->rgb_width, im2->rgb_height);
|
|
if (!im2->rgb_data)
|
|
{
|
|
free(im2);
|
|
return NULL;
|
|
}
|
|
memcpy(im2->rgb_data, im->rgb_data, im2->rgb_width * im2->rgb_height * 3);
|
|
if (im->alpha_data)
|
|
{
|
|
im2->alpha_data = malloc(im2->rgb_width * im2->rgb_height);
|
|
if (!im2->alpha_data)
|
|
{
|
|
free(im2->rgb_data);
|
|
free(im2);
|
|
return NULL;
|
|
}
|
|
memcpy(im2->alpha_data, im->alpha_data, im2->rgb_width * im2->rgb_height);
|
|
}
|
|
else
|
|
im2->alpha_data = NULL;
|
|
s = malloc(strlen(im->filename) + 320);
|
|
if (s)
|
|
{
|
|
snprintf(s, sizeof(s), "%s_%x_%x", im->filename, (int)time(NULL), (int)rand());
|
|
im2->filename = malloc(strlen(s) + 1);
|
|
if (im2->filename)
|
|
strcpy(im2->filename, s);
|
|
free(s);
|
|
}
|
|
else
|
|
im2->filename = NULL;
|
|
im2->width = 0;
|
|
im2->height = 0;
|
|
im2->shape_color.r = im->shape_color.r;
|
|
im2->shape_color.g = im->shape_color.g;
|
|
im2->shape_color.b = im->shape_color.b;
|
|
im2->border.left = im->border.left;
|
|
im2->border.right = im->border.right;
|
|
im2->border.top = im->border.top;
|
|
im2->border.bottom = im->border.bottom;
|
|
im2->pixmap = 0;
|
|
im2->shape_mask = 0;
|
|
im2->cache = 1;
|
|
im2->mod.gamma = im->mod.gamma;
|
|
im2->mod.brightness = im->mod.brightness;
|
|
im2->mod.contrast = im->mod.contrast;
|
|
im2->rmod.gamma = im->rmod.gamma;
|
|
im2->rmod.brightness = im->rmod.brightness;
|
|
im2->rmod.contrast = im->rmod.contrast;
|
|
im2->gmod.gamma = im->gmod.gamma;
|
|
im2->gmod.brightness = im->gmod.brightness;
|
|
im2->gmod.contrast = im->gmod.contrast;
|
|
im2->bmod.gamma = im->bmod.gamma;
|
|
im2->bmod.brightness = im->bmod.brightness;
|
|
im2->bmod.contrast = im->bmod.contrast;
|
|
calc_map_tables(id, im2);
|
|
if (id->cache.on_image)
|
|
add_image(id, im2, im2->filename);
|
|
return im2;
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_clone_scaled_image(ImlibData * id, ImlibImage * im, int w, int h)
|
|
{
|
|
ImlibImage *im2;
|
|
char *s;
|
|
|
|
if ((!im) || (w <= 0) || (h <= 0))
|
|
return NULL;
|
|
|
|
im2 = malloc(sizeof(ImlibImage));
|
|
if (!im2)
|
|
return NULL;
|
|
im2->rgb_width = w;
|
|
im2->rgb_height = h;
|
|
im2->rgb_data = _imlib_malloc_image(w, h);
|
|
if (!im2->rgb_data)
|
|
{
|
|
free(im2);
|
|
return NULL;
|
|
}
|
|
{
|
|
int x, y, *xarray;
|
|
unsigned char **yarray, *ptr, *ptr2, *ptr22;
|
|
int l, r, m, pos, inc, w3;
|
|
|
|
xarray = malloc(sizeof(int) * w);
|
|
|
|
if (!xarray)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot allocate X co-ord buffer\n");
|
|
free(im2->rgb_data);
|
|
free(im2);
|
|
return NULL;
|
|
}
|
|
yarray = malloc(sizeof(unsigned char *) * h);
|
|
|
|
if (!yarray)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot allocate Y co-ord buffer\n");
|
|
free(xarray);
|
|
free(im2->rgb_data);
|
|
free(im2);
|
|
return NULL;
|
|
}
|
|
ptr22 = im->rgb_data;
|
|
w3 = im->rgb_width * 3;
|
|
inc = 0;
|
|
if (w < im->border.left + im->border.right)
|
|
{
|
|
l = w >> 1;
|
|
r = w - l;
|
|
m = 0;
|
|
}
|
|
else
|
|
{
|
|
l = im->border.left;
|
|
r = im->border.right;
|
|
m = w - l - r;
|
|
}
|
|
if (m > 0)
|
|
inc = ((im->rgb_width - im->border.left - im->border.right) << 16) / m;
|
|
pos = 0;
|
|
if (l)
|
|
for (x = 0; x < l; x++)
|
|
{
|
|
xarray[x] = (pos >> 16) + (pos >> 16) + (pos >> 16);
|
|
pos += 0x10000;
|
|
}
|
|
if (m)
|
|
{
|
|
for (x = l; x < l + m; x++)
|
|
{
|
|
xarray[x] = (pos >> 16) + (pos >> 16) + (pos >> 16);
|
|
pos += inc;
|
|
}
|
|
}
|
|
pos = (im->rgb_width - r) << 16;
|
|
for (x = w - r; x < w; x++)
|
|
{
|
|
xarray[x] = (pos >> 16) + (pos >> 16) + (pos >> 16);
|
|
pos += 0x10000;
|
|
}
|
|
|
|
if (h < im->border.top + im->border.bottom)
|
|
{
|
|
l = h >> 1;
|
|
r = h - l;
|
|
m = 0;
|
|
}
|
|
else
|
|
{
|
|
l = im->border.top;
|
|
r = im->border.bottom;
|
|
m = h - l - r;
|
|
}
|
|
if (m > 0)
|
|
inc = ((im->rgb_height - im->border.top - im->border.bottom) << 16) / m;
|
|
pos = 0;
|
|
for (x = 0; x < l; x++)
|
|
{
|
|
yarray[x] = ptr22 + ((pos >> 16) * w3);
|
|
pos += 0x10000;
|
|
}
|
|
if (m)
|
|
{
|
|
for (x = l; x < l + m; x++)
|
|
{
|
|
yarray[x] = ptr22 + ((pos >> 16) * w3);
|
|
pos += inc;
|
|
}
|
|
}
|
|
pos = (im->rgb_height - r) << 16;
|
|
for (x = h - r; x < h; x++)
|
|
{
|
|
yarray[x] = ptr22 + ((pos >> 16) * w3);
|
|
pos += 0x10000;
|
|
}
|
|
|
|
ptr = im2->rgb_data;
|
|
for (y = 0; y < h; y++)
|
|
{
|
|
for (x = 0; x < w; x++)
|
|
{
|
|
ptr2 = yarray[y] + xarray[x];
|
|
*ptr++ = (int)*ptr2++;
|
|
*ptr++ = (int)*ptr2++;
|
|
*ptr++ = (int)*ptr2;
|
|
}
|
|
}
|
|
}
|
|
if (im->alpha_data)
|
|
{
|
|
im2->alpha_data = NULL;
|
|
/* yet to be filled in */
|
|
}
|
|
else
|
|
im2->alpha_data = NULL;
|
|
s = malloc(strlen(im->filename) + 320);
|
|
if (s)
|
|
{
|
|
snprintf(s, sizeof(s), "%s_%x_%x_%x_%x", im->filename, (int)time(NULL), w, h, (int)rand());
|
|
im2->filename = malloc(strlen(s) + 1);
|
|
if (im2->filename)
|
|
strcpy(im2->filename, s);
|
|
free(s);
|
|
}
|
|
else
|
|
im2->filename = NULL;
|
|
im2->width = 0;
|
|
im2->height = 0;
|
|
im2->shape_color.r = im->shape_color.r;
|
|
im2->shape_color.g = im->shape_color.g;
|
|
im2->shape_color.b = im->shape_color.b;
|
|
im2->border.left = im->border.left;
|
|
im2->border.right = im->border.right;
|
|
im2->border.top = im->border.top;
|
|
im2->border.bottom = im->border.bottom;
|
|
im2->pixmap = 0;
|
|
im2->shape_mask = 0;
|
|
im2->cache = 1;
|
|
im2->mod.gamma = im->mod.gamma;
|
|
im2->mod.brightness = im->mod.brightness;
|
|
im2->mod.contrast = im->mod.contrast;
|
|
im2->rmod.gamma = im->rmod.gamma;
|
|
im2->rmod.brightness = im->rmod.brightness;
|
|
im2->rmod.contrast = im->rmod.contrast;
|
|
im2->gmod.gamma = im->gmod.gamma;
|
|
im2->gmod.brightness = im->gmod.brightness;
|
|
im2->gmod.contrast = im->gmod.contrast;
|
|
im2->bmod.gamma = im->bmod.gamma;
|
|
im2->bmod.brightness = im->bmod.brightness;
|
|
im2->bmod.contrast = im->bmod.contrast;
|
|
calc_map_tables(id, im2);
|
|
if (id->cache.on_image)
|
|
add_image(id, im2, im2->filename);
|
|
return im2;
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_create_image_from_xpm_data(ImlibData * id, char **data)
|
|
{
|
|
ImlibImage *im;
|
|
unsigned char *ptr, *end;
|
|
int c, i, j, k, ncolors, cpp, comment, transp, quote, context,
|
|
len, count, done;
|
|
int w, h;
|
|
char *line, s[256], tok[128], col[256];
|
|
XColor xcol;
|
|
struct _cmap
|
|
{
|
|
char str[6];
|
|
char transp;
|
|
short r, g, b;
|
|
}
|
|
*cmap;
|
|
short lookup[128 - 32][128 - 32];
|
|
|
|
if (!data)
|
|
return NULL;
|
|
if (! id->x.disp)
|
|
return NULL;
|
|
im = malloc(sizeof(ImlibImage));
|
|
if (!im)
|
|
return NULL;
|
|
count = 0;
|
|
transp = 0;
|
|
done = 0;
|
|
|
|
j = 0;
|
|
cmap = NULL;
|
|
c = ' ';
|
|
comment = 0;
|
|
quote = 0;
|
|
context = 0;
|
|
ptr = NULL;
|
|
end = NULL;
|
|
|
|
while (!done)
|
|
{
|
|
line = data[count++];
|
|
if (context == 0)
|
|
{
|
|
/* Header */
|
|
sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp);
|
|
if (ncolors > 32766)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: XPM data wth colors > 32766 not supported\n");
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
if (cpp > 5)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: XPM data with characters per pixel > 5 not supported\n");
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
if (w > 32767)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for data\n");
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
if (h > 32767)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for data\n");
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
cmap = malloc(sizeof(struct _cmap) * ncolors);
|
|
|
|
if (!cmap)
|
|
{
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
im->rgb_width = w;
|
|
im->rgb_height = h;
|
|
im->rgb_data = malloc(im->rgb_width * im->rgb_height * 3);
|
|
if (!im->rgb_data)
|
|
{
|
|
free(cmap);
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
im->alpha_data = NULL;
|
|
snprintf (s, sizeof (s), "creat_%lx_%x", time(NULL), rand());
|
|
im->filename = strdup(s);
|
|
im->width = 0;
|
|
im->height = 0;
|
|
im->border.left = 0;
|
|
im->border.right = 0;
|
|
im->border.top = 0;
|
|
im->border.bottom = 0;
|
|
im->pixmap = 0;
|
|
im->shape_mask = 0;
|
|
im->cache = 1;
|
|
im->mod.gamma = id->mod.gamma;
|
|
im->mod.brightness = id->mod.brightness;
|
|
im->mod.contrast = id->mod.contrast;
|
|
im->rmod.gamma = id->rmod.gamma;
|
|
im->rmod.brightness = id->rmod.brightness;
|
|
im->rmod.contrast = id->rmod.contrast;
|
|
im->gmod.gamma = id->gmod.gamma;
|
|
im->gmod.brightness = id->gmod.brightness;
|
|
im->gmod.contrast = id->gmod.contrast;
|
|
im->bmod.gamma = id->bmod.gamma;
|
|
im->bmod.brightness = id->bmod.brightness;
|
|
im->bmod.contrast = id->bmod.contrast;
|
|
ptr = im->rgb_data;
|
|
end = im->rgb_data + (im->rgb_width * im->rgb_height * 3);
|
|
j = 0;
|
|
context++;
|
|
}
|
|
else if (context == 1)
|
|
{
|
|
int colptr;
|
|
int hascolor, iscolor;
|
|
|
|
/* Color Table */
|
|
if (j < ncolors)
|
|
{
|
|
iscolor = 0;
|
|
hascolor = 0;
|
|
tok[0] = 0;
|
|
col[0] = 0;
|
|
s[0] = 0;
|
|
colptr = 0;
|
|
len = strlen(line);
|
|
strncpy(cmap[j].str, line, cpp);
|
|
cmap[j].str[cpp] = 0;
|
|
cmap[j].r = -1;
|
|
cmap[j].transp = 0;
|
|
for (k = cpp; k < len; k++)
|
|
{
|
|
if (line[k] != ' ')
|
|
{
|
|
sscanf(&line[k], "%65536s", s);
|
|
k += strlen(s);
|
|
if (!strcmp(s, "c"))
|
|
iscolor = 1;
|
|
if ((!strcmp(s, "m")) || (!strcmp(s, "s")) ||
|
|
(!strcmp(s, "g4")) || (!strcmp(s, "g")) ||
|
|
(!strcmp(s, "c")) || (k >= len))
|
|
{
|
|
if (k >= len)
|
|
{
|
|
int ls;
|
|
|
|
ls = strlen(s);
|
|
|
|
if (col[0] && colptr < sizeof(col))
|
|
{
|
|
strcpy(col + colptr, " ");
|
|
colptr++;
|
|
}
|
|
if (colptr + ls <= sizeof(col))
|
|
{
|
|
strcpy(col + colptr, s);
|
|
colptr += ls;
|
|
}
|
|
|
|
}
|
|
if (col[0])
|
|
{
|
|
if (!strcasecmp(col, "none"))
|
|
{
|
|
transp = 1;
|
|
cmap[j].transp = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((((cmap[j].r < 0) ||
|
|
(!strcmp(tok, "c"))) &&
|
|
(!hascolor)))
|
|
{
|
|
XParseColor(id->x.disp,
|
|
id->x.root_cmap,
|
|
col, &xcol);
|
|
cmap[j].r = xcol.red >> 8;
|
|
cmap[j].g = xcol.green >> 8;
|
|
cmap[j].b = xcol.blue >> 8;
|
|
if ((cmap[j].r == 255) &&
|
|
(cmap[j].g == 0) &&
|
|
(cmap[j].b == 255))
|
|
cmap[j].r = 254;
|
|
if (iscolor)
|
|
hascolor = 1;
|
|
}
|
|
}
|
|
}
|
|
if (strlen(s) < sizeof(tok))
|
|
strcpy(tok, s);
|
|
col[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
int ls;
|
|
|
|
ls = strlen(s);
|
|
if (col[0] && colptr < sizeof(col))
|
|
{
|
|
strcpy(col + colptr, " ");
|
|
colptr++;
|
|
}
|
|
if (ls + colptr < sizeof(col))
|
|
{
|
|
strcpy(col + colptr, s);
|
|
colptr += ls;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
j++;
|
|
if (j >= ncolors)
|
|
{
|
|
if (cpp == 1)
|
|
for (i = 0; i < ncolors; i++)
|
|
lookup[(int)cmap[i].str[0] - 32][0] = i;
|
|
else if (cpp == 2)
|
|
for (i = 0; i < ncolors; i++)
|
|
lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i;
|
|
context++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Image Data */
|
|
i = 0;
|
|
if (cpp == 0)
|
|
{
|
|
}
|
|
else if (cpp == 1)
|
|
{
|
|
if (transp)
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i];
|
|
if (cmap[lookup[(int)col[0] - 32][0]].transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i];
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].b;
|
|
}
|
|
}
|
|
}
|
|
else if (cpp == 2)
|
|
{
|
|
if (transp)
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i++];
|
|
col[1] = line[i];
|
|
if (cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i++];
|
|
col[1] = line[i];
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (transp)
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
for (j = 0; j < cpp; j++, i++)
|
|
{
|
|
col[j] = line[i];
|
|
}
|
|
col[j] = 0;
|
|
i--;
|
|
for (j = 0; j < ncolors; j++)
|
|
{
|
|
if (!strcmp(col, cmap[j].str))
|
|
{
|
|
if (cmap[j].transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = (unsigned char)cmap[j].r;
|
|
*ptr++ = (unsigned char)cmap[j].g;
|
|
*ptr++ = (unsigned char)cmap[j].b;
|
|
}
|
|
j = ncolors;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
for (j = 0; j < cpp; j++, i++)
|
|
{
|
|
col[j] = line[i];
|
|
}
|
|
col[j] = 0;
|
|
i--;
|
|
for (j = 0; j < ncolors; j++)
|
|
{
|
|
if (!strcmp(col, cmap[j].str))
|
|
{
|
|
*ptr++ = (unsigned char)cmap[j].r;
|
|
*ptr++ = (unsigned char)cmap[j].g;
|
|
*ptr++ = (unsigned char)cmap[j].b;
|
|
j = ncolors;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((ptr) && ((ptr - im->rgb_data) >= w * h * 3))
|
|
done = 1;
|
|
}
|
|
if (!transp)
|
|
{
|
|
im->shape_color.r = -1;
|
|
im->shape_color.g = -1;
|
|
im->shape_color.b = -1;
|
|
}
|
|
else
|
|
{
|
|
im->shape_color.r = 255;
|
|
im->shape_color.g = 0;
|
|
im->shape_color.b = 255;
|
|
}
|
|
if (id->cache.on_image)
|
|
add_image(id, im, im->filename);
|
|
calc_map_tables(id, im);
|
|
free(cmap);
|
|
return im;
|
|
}
|
|
|
|
int
|
|
Imlib_data_to_pixmap(ImlibData * id, char **data, Pixmap * pmap, Pixmap * mask)
|
|
{
|
|
ImlibImage *im;
|
|
|
|
im = Imlib_create_image_from_xpm_data(id, data);
|
|
if (!im)
|
|
{
|
|
if (pmap)
|
|
*pmap = 0;
|
|
if (mask)
|
|
*mask = 0;
|
|
return 0;
|
|
}
|
|
if (!Imlib_render(id, im, im->rgb_width, im->rgb_height))
|
|
{
|
|
Imlib_destroy_image(id, im);
|
|
if (pmap)
|
|
*pmap = 0;
|
|
if (mask)
|
|
*mask = 0;
|
|
return 0;
|
|
}
|
|
if (pmap)
|
|
*pmap = Imlib_move_image(id, im);
|
|
if (mask)
|
|
*mask = Imlib_move_mask(id, im);
|
|
Imlib_kill_image(id, im);
|
|
return 1;
|
|
}
|
|
|
|
struct _io_info
|
|
{
|
|
unsigned char *data;
|
|
unsigned char *ptr;
|
|
unsigned char *end;
|
|
};
|
|
|
|
#ifdef HAVE_LIBPNG
|
|
static void
|
|
_png_io_read(png_structp png_ptr,
|
|
png_bytep data, png_uint_32 size)
|
|
{
|
|
struct _io_info *io_ptr;
|
|
int bytes;
|
|
|
|
io_ptr = (struct _io_info *)png_get_io_ptr(png_ptr);
|
|
|
|
if ((io_ptr->end - io_ptr->ptr) >= size)
|
|
{
|
|
memcpy(data, io_ptr->ptr, size);
|
|
io_ptr->ptr += size;
|
|
return;
|
|
}
|
|
bytes = io_ptr->end - io_ptr->ptr;
|
|
memcpy(data, io_ptr->ptr, bytes);
|
|
io_ptr->ptr = io_ptr->end;
|
|
return;
|
|
}
|
|
#endif /* HAVE_LIBPNG */
|
|
|
|
ImlibImage *
|
|
Imlib_inlined_png_to_image(ImlibData *id, unsigned char *data, int data_size)
|
|
{
|
|
#ifdef HAVE_LIBPNG
|
|
ImlibImage *im;
|
|
png_structp png_ptr;
|
|
png_infop info_ptr;
|
|
unsigned char *ptr, **lines, *ptr2, r, g, b, a;
|
|
int i, x, y, transp, bit_depth, color_type, interlace_type;
|
|
png_uint_32 ww, hh;
|
|
char s[512];
|
|
struct _io_info io_info;
|
|
|
|
im = malloc(sizeof(ImlibImage));
|
|
if (!im)
|
|
return NULL;
|
|
im->rgb_width = 0;
|
|
im->rgb_height = 0;
|
|
im->rgb_data = NULL;
|
|
im->alpha_data = NULL;
|
|
snprintf(s, sizeof(s), "creat_%x_%x", (int)time(NULL), (int)rand());
|
|
im->filename = malloc(strlen(s) + 1);
|
|
if (im->filename)
|
|
strcpy(im->filename, s);
|
|
im->width = 0;
|
|
im->height = 0;
|
|
im->border.left = 0;
|
|
im->border.right = 0;
|
|
im->border.top = 0;
|
|
im->border.bottom = 0;
|
|
im->pixmap = 0;
|
|
im->shape_mask = 0;
|
|
im->cache = 1;
|
|
im->mod.gamma = id->mod.gamma;
|
|
im->mod.brightness = id->mod.brightness;
|
|
im->mod.contrast = id->mod.contrast;
|
|
im->rmod.gamma = id->rmod.gamma;
|
|
im->rmod.brightness = id->rmod.brightness;
|
|
im->rmod.contrast = id->rmod.contrast;
|
|
im->gmod.gamma = id->gmod.gamma;
|
|
im->gmod.brightness = id->gmod.brightness;
|
|
im->gmod.contrast = id->gmod.contrast;
|
|
im->bmod.gamma = id->bmod.gamma;
|
|
im->bmod.brightness = id->bmod.brightness;
|
|
im->bmod.contrast = id->bmod.contrast;
|
|
im->shape_color.r = -1;
|
|
im->shape_color.g = -1;
|
|
im->shape_color.b = -1;
|
|
/* Init PNG Reader */
|
|
transp = 0;
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
if (!png_ptr)
|
|
return NULL;
|
|
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
if (!info_ptr)
|
|
{
|
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if (setjmp(png_ptr->jmpbuf))
|
|
{
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
|
{
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
io_info.data = data;
|
|
io_info.ptr = data;
|
|
io_info.end = data + data_size;
|
|
png_set_read_fn(png_ptr, (void *)(&io_info), (png_rw_ptr)_png_io_read);
|
|
|
|
/* Read Header */
|
|
png_read_info(png_ptr, info_ptr);
|
|
png_get_IHDR(png_ptr, info_ptr, &ww, &hh, &bit_depth, &color_type, &interlace_type,
|
|
NULL, NULL);
|
|
im->rgb_width = ww;
|
|
im->rgb_height = hh;
|
|
/* Setup Translators */
|
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
|
png_set_expand(png_ptr);
|
|
png_set_strip_16(png_ptr);
|
|
png_set_packing(png_ptr);
|
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
|
png_set_expand(png_ptr);
|
|
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
|
im->rgb_data = malloc(ww * hh * 3);
|
|
if (!(im->rgb_data))
|
|
{
|
|
free(im->filename);
|
|
free(im);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
lines = (unsigned char **)malloc(hh * sizeof(unsigned char *));
|
|
|
|
if (lines == NULL)
|
|
{
|
|
free(im->filename);
|
|
free(im);
|
|
free(im->rgb_data);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < hh; i++)
|
|
{
|
|
if ((lines[i] = malloc(ww * (sizeof(unsigned char) * 4))) == NULL)
|
|
{
|
|
int n;
|
|
|
|
free(im->filename);
|
|
free(im);
|
|
free(im->rgb_data);
|
|
for (n = 0; n < i; n++)
|
|
free(lines[n]);
|
|
free(lines);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
}
|
|
png_read_image(png_ptr, lines);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
ptr = im->rgb_data;
|
|
if ((color_type == PNG_COLOR_TYPE_GRAY) ||
|
|
(color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
|
|
{
|
|
for (y = 0; y < hh; y++)
|
|
{
|
|
ptr2 = lines[y];
|
|
for (x = 0; x < ww; x++)
|
|
{
|
|
r = *ptr2++;
|
|
a = *ptr2++;
|
|
if (a < 128)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
transp = 1;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = r;
|
|
*ptr++ = r;
|
|
*ptr++ = r;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (y = 0; y < hh; y++)
|
|
{
|
|
ptr2 = lines[y];
|
|
for (x = 0; x < ww; x++)
|
|
{
|
|
r = *ptr2++;
|
|
g = *ptr2++;
|
|
b = *ptr2++;
|
|
a = *ptr2++;
|
|
if (a < 128)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
transp = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((r == 255) && (g == 0) && (b == 255))
|
|
r = 254;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < hh; i++)
|
|
free(lines[i]);
|
|
free(lines);
|
|
if (transp)
|
|
{
|
|
im->shape_color.r = 255;
|
|
im->shape_color.g = 0;
|
|
im->shape_color.b = 255;
|
|
}
|
|
if (id->cache.on_image)
|
|
add_image(id, im, im->filename);
|
|
calc_map_tables(id, im);
|
|
return im;
|
|
#else
|
|
return NULL;
|
|
#endif /* HAVE_LIBPNG */
|
|
}
|
|
|
|
|
|
#include <signal.h>
|
|
#include <sys/wait.h>
|
|
|
|
/* Helper library */
|
|
|
|
static int hpid;
|
|
void (*oldpiper) (int); /* actually sighandler_t but BSD uses sig_t. */
|
|
|
|
static char x_error = 0;
|
|
|
|
static void
|
|
__handle_x_error(Display * d, XErrorEvent * ev)
|
|
{
|
|
d = NULL;
|
|
ev = NULL;
|
|
x_error = 1;
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_create_image_from_drawable(ImlibData * id, Drawable win, Pixmap mask,
|
|
int x, int y, int width, int height)
|
|
{
|
|
unsigned char *data = NULL, *ptr, r, g, b;
|
|
unsigned long pixel;
|
|
int i, xx, yy, w, h, inx, iny, clipx, clipy, rx, ry;
|
|
XImage *xim;
|
|
|
|
#ifdef HAVE_SHM
|
|
XShmSegmentInfo shminfo;
|
|
|
|
#endif
|
|
XWindowAttributes xatt, ratt;
|
|
Colormap cmap;
|
|
static char shm_checked = 0, shm = 1;
|
|
XErrorHandler erh = NULL;
|
|
Window chld;
|
|
char is_pixmap = 0;
|
|
Visual *vis;
|
|
ImlibImage *im;
|
|
ImlibColor ctab[256];
|
|
Display *disp;
|
|
|
|
inx = 0;
|
|
iny = 0;
|
|
w = width;
|
|
h = height;
|
|
vis = id->x.visual;
|
|
disp = id->x.disp;
|
|
|
|
XGrabServer(disp);
|
|
erh = XSetErrorHandler((XErrorHandler) __handle_x_error);
|
|
x_error = 0;
|
|
XGetWindowAttributes(disp, win, &xatt);
|
|
XFlush(disp);
|
|
if (x_error)
|
|
{
|
|
x_error = 0;
|
|
is_pixmap = 1;
|
|
XGetGeometry(disp, win, &chld, &rx, &rx,
|
|
(unsigned int *)&xatt.width, (unsigned int *)&xatt.height,
|
|
(unsigned int *)&rx, (unsigned int *)&xatt.depth);
|
|
XFlush(disp);
|
|
if (x_error)
|
|
{
|
|
XUngrabServer(disp);
|
|
XFlush(disp);
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
return NULL;
|
|
}
|
|
}
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
if (!is_pixmap)
|
|
{
|
|
XGetWindowAttributes(disp, xatt.root, &ratt);
|
|
XTranslateCoordinates(disp, win, xatt.root, 0, 0, &rx, &ry, &chld);
|
|
if ((xatt.map_state != IsViewable) &&
|
|
(xatt.backing_store == NotUseful))
|
|
{
|
|
XUngrabServer(disp);
|
|
XFlush(disp);
|
|
return NULL;
|
|
}
|
|
}
|
|
clipx = 0;
|
|
clipy = 0;
|
|
|
|
x = x - inx;
|
|
y = y - iny;
|
|
|
|
width = xatt.width - x;
|
|
height = xatt.height - y;
|
|
if (width > w)
|
|
width = w;
|
|
if (height > h)
|
|
height = h;
|
|
|
|
if (!is_pixmap)
|
|
{
|
|
if ((rx + x + width) > ratt.width)
|
|
width = ratt.width - (rx + x);
|
|
if ((ry + y + height) > ratt.height)
|
|
height = ratt.height - (ry + y);
|
|
}
|
|
if (x < 0)
|
|
{
|
|
clipx = -x;
|
|
width += x;
|
|
x = 0;
|
|
}
|
|
if (y < 0)
|
|
{
|
|
clipy = -y;
|
|
height += y;
|
|
y = 0;
|
|
}
|
|
if (!is_pixmap)
|
|
{
|
|
if ((rx + x) < 0)
|
|
{
|
|
clipx -= (rx + x);
|
|
width += (rx + x);
|
|
x = -rx;
|
|
}
|
|
if ((ry + y) < 0)
|
|
{
|
|
clipy -= (ry + y);
|
|
height += (ry + y);
|
|
y = -ry;
|
|
}
|
|
}
|
|
if ((width <= 0) || (height <= 0))
|
|
{
|
|
XUngrabServer(disp);
|
|
XSync(disp, False);
|
|
return NULL;
|
|
}
|
|
#ifdef HAVE_SHM
|
|
if (shm)
|
|
{
|
|
if (!shm_checked)
|
|
{
|
|
erh = XSetErrorHandler((XErrorHandler) __handle_x_error);
|
|
}
|
|
xim = XShmCreateImage(disp, vis, xatt.depth, ZPixmap, NULL,
|
|
&shminfo, width, height);
|
|
if (!shm_checked)
|
|
{
|
|
XSync(disp, False);
|
|
if (x_error)
|
|
{
|
|
shm = 0;
|
|
XDestroyImage(xim);
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
shm_checked = 1;
|
|
}
|
|
else
|
|
{
|
|
shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line *
|
|
xim->height, IPC_CREAT | 0666);
|
|
if (shminfo.shmid < 0)
|
|
{
|
|
shm = 0;
|
|
XDestroyImage(xim);
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
shm_checked = 1;
|
|
}
|
|
else
|
|
{
|
|
shminfo.shmaddr = xim->data = shmat(shminfo.shmid, 0, 0);
|
|
if (shminfo.shmaddr == (char *)-1)
|
|
{
|
|
shm = 0;
|
|
XDestroyImage(xim);
|
|
shmctl(shminfo.shmid, IPC_RMID, 0);
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
shm_checked = 1;
|
|
}
|
|
else
|
|
{
|
|
shminfo.readOnly = False;
|
|
XShmAttach(disp, &shminfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line *
|
|
xim->height, IPC_CREAT | 0666);
|
|
if (shminfo.shmid < 0)
|
|
{
|
|
shm = 0;
|
|
XDestroyImage(xim);
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
shm_checked = 1;
|
|
}
|
|
else
|
|
{
|
|
shminfo.shmaddr = xim->data = shmat(shminfo.shmid, 0, 0);
|
|
if (shminfo.shmaddr == (char *)-1)
|
|
{
|
|
shm = 0;
|
|
XDestroyImage(xim);
|
|
shmctl(shminfo.shmid, IPC_RMID, 0);
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
shm_checked = 1;
|
|
}
|
|
else
|
|
{
|
|
shminfo.readOnly = False;
|
|
XShmAttach(disp, &shminfo);
|
|
}
|
|
}
|
|
}
|
|
if (!shm_checked)
|
|
{
|
|
XSync(disp, False);
|
|
if (x_error)
|
|
{
|
|
shm = 0;
|
|
XDestroyImage(xim);
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
shm_checked = 1;
|
|
}
|
|
XSetErrorHandler((XErrorHandler) erh);
|
|
shm_checked = 1;
|
|
}
|
|
}
|
|
else
|
|
#endif /* HAVE_SHM */
|
|
xim = XGetImage(disp, win, x, y, width, height, 0xffffffff, ZPixmap);
|
|
#ifdef HAVE_SHM
|
|
if (shm)
|
|
XShmGetImage(disp, win, xim, x, y, 0xffffffff);
|
|
#endif
|
|
XUngrabServer(disp);
|
|
XFlush(disp);
|
|
|
|
if (xatt.depth == 1)
|
|
{
|
|
ctab[0].r = 255;
|
|
ctab[0].g = 255;
|
|
ctab[0].b = 255;
|
|
ctab[1].r = 0;
|
|
ctab[1].g = 0;
|
|
ctab[1].b = 0;
|
|
}
|
|
else if (xatt.depth <= 8)
|
|
{
|
|
XColor cols[256];
|
|
|
|
if (!is_pixmap)
|
|
{
|
|
cmap = xatt.colormap;
|
|
if (cmap == None)
|
|
cmap = id->x.root_cmap;
|
|
}
|
|
else
|
|
cmap = id->x.root_cmap;
|
|
|
|
for (i = 0; i < (1 << id->x.depth); i++)
|
|
{
|
|
cols[i].pixel = i;
|
|
cols[i].flags = DoRed | DoGreen | DoBlue;
|
|
}
|
|
XQueryColors(disp, cmap, cols, 1 << id->x.depth);
|
|
for (i = 0; i < (1 << id->x.depth); i++)
|
|
{
|
|
ctab[i].r = cols[i].red >> 8;
|
|
ctab[i].g = cols[i].green >> 8;
|
|
ctab[i].b = cols[i].blue >> 8;
|
|
ctab[i].pixel = cols[i].pixel;
|
|
}
|
|
}
|
|
data = malloc(width * height * 3);
|
|
if (data)
|
|
{
|
|
ptr = data;
|
|
switch (xatt.depth)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
for (yy = 0; yy < height; yy++)
|
|
{
|
|
for (xx = 0; xx < width; xx++)
|
|
{
|
|
pixel = XGetPixel(xim, xx, yy);
|
|
r = ctab[pixel & 0xff].r;
|
|
g = ctab[pixel & 0xff].g;
|
|
b = ctab[pixel & 0xff].b;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
break;
|
|
case 16:
|
|
case 15:
|
|
if (id->x.render_depth == 16)
|
|
{
|
|
for (yy = 0; yy < height; yy++)
|
|
{
|
|
for (xx = 0; xx < width; xx++)
|
|
{
|
|
pixel = XGetPixel(xim, xx, yy);
|
|
r = (pixel >> 8) & 0xf8;
|
|
g = (pixel >> 3) & 0xfc;
|
|
b = (pixel << 3) & 0xf8;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (yy = 0; yy < height; yy++)
|
|
{
|
|
for (xx = 0; xx < width; xx++)
|
|
{
|
|
pixel = XGetPixel(xim, xx, yy);
|
|
r = (pixel >> 7) & 0xf8;
|
|
g = (pixel >> 2) & 0xf8;
|
|
b = (pixel << 3) & 0xf8;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 24:
|
|
case 32:
|
|
for (yy = 0; yy < height; yy++)
|
|
{
|
|
for (xx = 0; xx < width; xx++)
|
|
{
|
|
pixel = XGetPixel(xim, xx, yy);
|
|
r = (pixel >> 16) & 0xff;
|
|
g = (pixel >> 8) & 0xff;
|
|
b = pixel & 0xff;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
for (yy = 0; yy < height; yy++)
|
|
{
|
|
for (xx = 0; xx < width; xx++)
|
|
{
|
|
r = rand();
|
|
g = rand();
|
|
b = rand();
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_SHM
|
|
if (shm)
|
|
{
|
|
XSync(disp, False);
|
|
XShmDetach(disp, &shminfo);
|
|
shmdt(shminfo.shmaddr);
|
|
shmctl(shminfo.shmid, IPC_RMID, 0);
|
|
}
|
|
#endif
|
|
XDestroyImage(xim);
|
|
|
|
if (data)
|
|
{
|
|
im = Imlib_create_image_from_data(id, data, NULL, width, height);
|
|
free(data);
|
|
return im;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|