e16/src/eimage.c

511 lines
12 KiB
C

/*
* Copyright (C) 2004-2007 Kim Woelders
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
#include "eimage.h"
#include "xwin.h"
#include <Imlib2.h>
static Window _default_draw;
static Visual *_default_vis;
static Colormap _default_cmap;
void
EImageInit(Display * dpy)
{
imlib_set_cache_size(2048 * 1024);
imlib_set_font_cache_size(512 * 1024);
imlib_set_color_usage(128);
_default_draw = DefaultRootWindow(dpy);
_default_vis = DefaultVisual(dpy, DefaultScreen(dpy));
_default_cmap = DefaultColormap(dpy, DefaultScreen(dpy));
imlib_context_set_display(dpy);
imlib_context_set_visual(_default_vis);
imlib_context_set_colormap(_default_cmap);
#ifdef HAVE_IMLIB_CONTEXT_SET_MASK_ALPHA_THRESHOLD
imlib_context_set_mask_alpha_threshold(Conf.testing.mask_alpha_threshold);
#endif
imlib_context_set_dither(1);
}
EImage *
EImageLoad(const char *file)
{
return imlib_load_image(file);
}
void
EImageSave(EImage * im, const char *file)
{
imlib_context_set_image(im);
imlib_image_set_format("png");
imlib_save_image(file);
}
EImage *
EImageCreate(int w, int h)
{
EImage *im;
im = imlib_create_image(w, h);
return im;
}
EImage *
EImageCreateFromData(int w, int h, unsigned int *data)
{
EImage *im;
im = imlib_create_image_using_copied_data(w, h, data);
return im;
}
EImage *
EImageCreateScaled(EImage * im, int sx, int sy, int sw, int sh, int dw, int dh)
{
imlib_context_set_image(im);
if (sw <= 0)
sw = imlib_image_get_width();
if (sh <= 0)
sh = imlib_image_get_height();
if (dw <= 0)
dw = sw;
if (dh <= 0)
dh = sh;
return imlib_create_cropped_scaled_image(sx, sy, sw, sh, dw, dh);
}
void
EImageFree(EImage * im)
{
imlib_context_set_image(im);
imlib_free_image();
}
void
EImageDecache(EImage * im)
{
imlib_context_set_image(im);
imlib_free_image_and_decache();
}
static int
_EImageCheckAlpha(void)
{
static const short oink = 3; /* For endianness checking */
unsigned char *pb, *pe;
if (!imlib_image_has_alpha())
return 0;
pb = (unsigned char *)imlib_image_get_data_for_reading_only();
pe = pb + 4 * imlib_image_get_width() * imlib_image_get_height();
pb += *((char *)(&oink));
for (; pb < pe; pb += 4)
if (*pb != 0xff)
return 1;
return 0;
}
void
EImageCheckAlpha(EImage * im)
{
imlib_context_set_image(im);
if (imlib_image_has_alpha() && !_EImageCheckAlpha())
{
#if 0
Eprintf("Alpha set but no shape %s\n", is->real_file);
#endif
imlib_image_set_has_alpha(0);
}
}
void
EImageSetHasAlpha(EImage * im, int has_alpha)
{
imlib_context_set_image(im);
imlib_image_set_has_alpha(has_alpha);
}
void
EImageSetBorder(EImage * im, EImageBorder * border)
{
Imlib_Border ib;
ib.left = border->left;
ib.right = border->right;
ib.top = border->top;
ib.bottom = border->bottom;
imlib_context_set_image(im);
imlib_image_set_border(&ib);
}
int
EImageHasAlpha(EImage * im)
{
imlib_context_set_image(im);
return imlib_image_has_alpha();
}
void
EImageGetSize(EImage * im, int *pw, int *ph)
{
imlib_context_set_image(im);
*pw = imlib_image_get_width();
*ph = imlib_image_get_height();
}
void *
EImageGetData(EImage * im)
{
imlib_context_set_image(im);
return imlib_image_get_data_for_reading_only();
}
void
EImageFill(EImage * im, int x, int y, int w, int h, int r, int g, int b, int a)
{
imlib_context_set_image(im);
imlib_context_set_color(r, g, b, a);
imlib_context_set_blend(0);
imlib_image_fill_rectangle(x, y, w, h);
}
void
EImageOrientate(EImage * im, int orientation)
{
imlib_context_set_image(im);
imlib_image_orientate(orientation);
}
void
EImageBlend(EImage * im, EImage * src, int blend,
int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh, int merge_alpha, int anti_alias)
{
imlib_context_set_image(im);
if (anti_alias)
imlib_context_set_anti_alias(1);
if (blend)
imlib_context_set_blend(1);
imlib_blend_image_onto_image(src, merge_alpha, sx, sy, sw, sh,
dx, dy, dw, dh);
if (blend)
imlib_context_set_blend(0);
if (anti_alias)
imlib_context_set_anti_alias(0);
}
void
EImageBlendCM(EImage * im, EImage * src, EImageColorModifier * icm)
{
int w, h, iw, ih;
imlib_context_set_image(src);
iw = imlib_image_get_width();
ih = imlib_image_get_height();
imlib_context_set_image(im);
w = imlib_image_get_width();
h = imlib_image_get_height();
imlib_context_set_blend(1);
if (icm)
imlib_context_set_color_modifier(icm);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_blend_image_onto_image(src, 0, 0, 0, iw, ih, 0, 0, w, h);
imlib_context_set_blend(0);
if (icm)
imlib_context_set_color_modifier(NULL);
}
void
EImageTile(EImage * im, EImage * tile, int blend, int tw, int th,
int dx, int dy, int dw, int dh, int ox, int oy)
{
Imlib_Image *tim;
int x, y, tx, ty, ww, hh;
int sw, sh;
if (tw <= 0 || th <= 0)
return;
imlib_context_set_image(tile);
sw = imlib_image_get_width();
sh = imlib_image_get_height();
if (sw == tw && sh == th)
{
tim = tile;
}
else
{
tim = imlib_create_image(tw, th);
imlib_context_set_image(tim);
imlib_context_set_blend(0);
imlib_blend_image_onto_image(tile, 0, 0, 0, sw, sh, 0, 0, tw, th);
}
imlib_context_set_image(im);
if (ox)
{
ox = tw - ox;
ox %= tw;
if (ox < 0)
ox += tw;
}
if (oy)
{
oy = th - oy;
oy %= th;
if (oy < 0)
oy += th;
}
dw += dx;
dh += dy;
y = dy;
ty = oy;
hh = th - oy;
for (;;)
{
if (y + hh >= dh)
hh = dh - y;
if (hh <= 0)
break;
x = dx;
tx = ox;
ww = tw - ox;
for (;;)
{
if (x + ww >= dw)
ww = dw - x;
if (ww <= 0)
break;
imlib_blend_image_onto_image(tim, blend, tx, ty, ww, hh,
x, y, ww, hh);
tx = 0;
x += ww;
ww = tw;
}
ty = 0;
y += hh;
hh = th;
}
if (tim != tile)
{
imlib_context_set_image(tim);
imlib_free_image();
imlib_context_set_image(im); /* FIXME - Remove */
}
}
EImage *
EImageGrabDrawable(Drawable draw, Pixmap mask, int x, int y, int w, int h,
int grab)
{
EImage *im;
Colormap cm;
cm = imlib_context_get_colormap();
imlib_context_set_colormap(None); /* Fix for grabbing bitmaps */
imlib_context_set_drawable(draw);
im = imlib_create_image_from_drawable(mask, x, y, w, h, grab);
imlib_context_set_colormap(cm);
return im;
}
EImage *
EImageGrabDrawableScaled(Win win, Drawable draw, Pixmap mask,
int x, int y, int w, int h,
int iw, int ih, int grab, int get_mask_from_shape)
{
EImage *im;
Visual *vis;
imlib_context_set_drawable(draw);
vis = (win) ? WinGetVisual(win) : NULL;
if (vis)
imlib_context_set_visual(vis);
im = imlib_create_scaled_image_from_drawable(mask, x, y, w, h, iw, ih, grab,
get_mask_from_shape);
if (vis)
imlib_context_set_visual(_default_vis);
return im;
}
void
EImageRenderOnDrawable(EImage * im, Win win, Drawable draw, int x, int y,
int w, int h, int blend)
{
Visual *vis;
imlib_context_set_image(im);
imlib_context_set_drawable((draw != None) ? draw : WinGetXwin(win));
vis = (win) ? WinGetVisual(win) : NULL;
if (vis)
imlib_context_set_visual(vis);
if (blend)
imlib_context_set_blend(1);
imlib_render_image_on_drawable_at_size(x, y, w, h);
if (blend)
imlib_context_set_blend(0);
if (vis)
imlib_context_set_visual(_default_vis);
}
void
EImageRenderPixmaps(EImage * im, Win win, Pixmap * pmap, Pixmap * mask,
int w, int h)
{
Visual *vis;
Pixmap m;
imlib_context_set_image(im);
imlib_context_set_drawable((win) ? WinGetXwin(win) : _default_draw);
vis = (win) ? WinGetVisual(win) : NULL;
if (vis)
imlib_context_set_visual(vis);
*pmap = None;
if (!mask) /* Imlib2 <= 1.3.0 needs a mask pointer */
mask = &m; /* ... to avoid bogus error messages */
if (mask)
*mask = None;
if (w <= 0 || h <= 0)
imlib_render_pixmaps_for_whole_image(pmap, mask);
else
imlib_render_pixmaps_for_whole_image_at_size(pmap, mask, w, h);
if (vis)
imlib_context_set_visual(_default_vis);
}
void
EImagePixmapFree(Pixmap pmap)
{
imlib_free_pixmap_and_mask(pmap);
}
void
ScaleRect(Win wsrc, Drawable src, Win wdst, Pixmap dst, Pixmap * pdst,
int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh, int scale)
{
Imlib_Image *im;
scale = (scale) ? 2 : 1;
im = EImageGrabDrawableScaled(wsrc, src, None, sx, sy, sw, sh,
scale * dw, scale * dh, 0, 0);
imlib_context_set_anti_alias(1);
if (pdst)
{
EImageRenderPixmaps(im, wdst, pdst, None, dw, dh);
}
else
{
EImageRenderOnDrawable(im, wdst, dst, dx, dy, dw, dh, 0);
}
imlib_free_image();
}
void
EDrawableDumpImage(Drawable draw, const char *txt)
{
static int seqn = 0;
char buf[1024];
Imlib_Image *im;
int w, h;
w = h = 0;
EXGetGeometry(draw, NULL, NULL, NULL, &w, &h, NULL, NULL);
if (w <= 0 || h <= 0)
return;
imlib_context_set_drawable(draw);
im = imlib_create_image_from_drawable(None, 0, 0, w, h, !EServerIsGrabbed());
imlib_context_set_image(im);
imlib_image_set_format("png");
sprintf(buf, "%s-%#lx-%d.png", txt, draw, seqn++);
Eprintf("EDrawableDumpImage: %s\n", buf);
imlib_save_image(buf);
imlib_free_image_and_decache();
}
void
FreePmapMask(PmapMask * pmm)
{
/* type !=0: Created by imlib_render_pixmaps_for_whole_image... */
if (pmm->pmap)
{
if (pmm->type == 0)
EFreePixmap(pmm->pmap);
else
imlib_free_pixmap_and_mask(pmm->pmap);
pmm->pmap = 0;
}
if (pmm->mask)
{
if (pmm->type == 0)
EFreePixmap(pmm->mask);
pmm->mask = 0;
}
}
EImageColorModifier *
EImageColorModifierCreate(void)
{
return imlib_create_color_modifier();
}
void
EImageColorModifierSetTables(EImageColorModifier * icm,
unsigned char *r, unsigned char *g,
unsigned char *b, unsigned char *a)
{
if (!icm)
return;
imlib_context_set_color_modifier(icm);
#if 0 /* Useful in this context? */
imlib_modify_color_modifier_gamma(0.5);
imlib_modify_color_modifier_brightness(0.5);
imlib_modify_color_modifier_contrast(0.5);
#endif
imlib_set_color_modifier_tables(r, g, b, a);
imlib_context_set_color_modifier(NULL);
}