adding imlib2 code in.. NOT a lib yet... :) but playable code and loader
system SVN revision: 27
This commit is contained in:
commit
520edea668
|
@ -0,0 +1,27 @@
|
|||
INSTALL = install
|
||||
|
||||
SRCS = rend.c ximage.c scale.c main.c rgba.c image.c color.c grab.c \
|
||||
blend.c file.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
BINDIR = /usr/local/bin
|
||||
BIN = imlib2
|
||||
LIBS = -L/usr/X11R6/lib/ -lX11 -lXext -ldl
|
||||
|
||||
CFLAGS = -O -g -mpentium -mcpu=pentium -march=pentium
|
||||
|
||||
imlib2: $(OBJS)
|
||||
$(RM) $@
|
||||
$(CC) -o $@ $(OBJS) $(LIBS)
|
||||
$(CC) loader_png.c -o png.so -Wl,-soname -Wl,png.so -shared -lpng -lz -lm
|
||||
|
||||
clean::
|
||||
$(RM) $(BIN) *.CKP *.ln *.BAK *.bak *.o *.so core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut "#"*
|
||||
|
||||
c.o:
|
||||
$(CC) $(CFLAGS) -I/usr/X11R6/include -c $< -o $@
|
||||
load.o:
|
||||
$(CC) $(CFLAGS) -I/usr/X11R6/include -c $< -o $@
|
||||
|
||||
install::
|
||||
$(INSTALL) $(BIN) $(BINDIR)
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
Imlib 2.0 pre pre pre pre alpha toy code...
|
||||
|
||||
WARNING!
|
||||
|
||||
this isn't even a library yet - it's a single program thats modularised to
|
||||
become a librayr once it's all debugged.
|
||||
|
||||
what you DO have here is:
|
||||
|
||||
color allocation & adjustment code - if in 8bbp or less it will cose the
|
||||
larges colorcube it can that fits in your available colormap space - right
|
||||
now the code uses the default colormap, but if you look at color.c carefully
|
||||
you'll see the code will not be hard to change (have prefercnes as to size
|
||||
of colorcube etc.)
|
||||
|
||||
does alpha blending onto any X drawable with any colormap.
|
||||
does ``high quality'' rendering with dithering available for all modes up to
|
||||
16bpp (1bpp, 8bpp, 15bpp, 16bpp).
|
||||
|
||||
probably has nasty endianess problems.
|
||||
|
||||
has VERY VERY VERY fast rendering code.
|
||||
has anti-aliased scaling up and down code.
|
||||
|
||||
has a modularised loader system (works right now - but still possible
|
||||
changes might have to be made)
|
||||
simple to get this going:
|
||||
mkdir ~/.loaders
|
||||
mkdir ~/.loaders/image
|
||||
cp png.so ~/.loaders/image
|
||||
|
||||
you just installed the png loader - it's theonly one i've written and it
|
||||
isnt very good (comments in code - load.c) but it works.
|
||||
the laoder system automagically updates yhe loaders were you to dump new
|
||||
files there or overwrite the old ones to any program RUNTIME will pick up
|
||||
the new code.. :) you dont even have to restart the program.. OOH what joy :)
|
||||
the image caching is all there and the pixmap caching backend is there too.
|
||||
there is nothign to generate pixmaps yet - that has yet to come (it will use
|
||||
the rendering code in rend.c).
|
||||
|
||||
things that still need to be worked on:
|
||||
* colormodifiers (to do gamma etc. correction - need to develop a new system
|
||||
wherby i can uniquely tag pixmaps with a colormodifier ID for caching
|
||||
properly).
|
||||
* border scaling - you know - like E does now for buttons etc.
|
||||
* saving functions
|
||||
* image manipulation funcitons (flip, rotate, scale etc of original data)
|
||||
* nice api for the actual library with context-like system (the api you see
|
||||
here is actually going to be the internal api for imlib - a level down from
|
||||
what api the user actually gets to see & use - all access to image data will
|
||||
be goverend by going thru the api too rather than just snarfing structure
|
||||
memebrs)
|
||||
* a new name for imlib2.0 - 2.0 just sounds boring :)
|
||||
* more loader / saver modules for jpeg, ppm, pgm, pgm, xpm, tiff etc...
|
||||
* RGBA drawing area - basically a RGBA buffer with RGBA buffer ops written
|
||||
(copyarea, poasteimage, fillrect, drawline, drawtext etc. so you can have a
|
||||
little virtual RGBA framebuffer - also will include rectangle os ineterst
|
||||
updating mechanism (so anly the parts of the RGBA buffer that were drawn to
|
||||
are drawn and updated to the scren).
|
||||
* more flim!
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#include "common.h"
|
||||
#include "blend.h"
|
||||
|
||||
void
|
||||
BlendRGBAToRGBA(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
|
||||
int w, int h)
|
||||
{
|
||||
int x, y;
|
||||
DATA32 *p1, *p2;
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
DATA8 a, nr, ng, nb, r, g, b, rr, gg, bb;
|
||||
int tmp;
|
||||
|
||||
p1 = src + (y * (w + src_jump));
|
||||
p2 = dst + (y * (w + dst_jump));
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
a = (*p1 >> 24) & 0xff;
|
||||
if (a < 255)
|
||||
{
|
||||
#if 1
|
||||
r = 255 - a;
|
||||
*p2 =
|
||||
((((*p1 & 0x00ff00ff) * a) >> 8) & 0x00ff00ff) +
|
||||
((((*p1 >> 8) & 0x00ff00ff) * a) & 0xff00ff00) +
|
||||
((((*p2 & 0x00ff00ff) * r) >> 8) & 0x00ff00ff) +
|
||||
((((*p2 >> 8) & 0x00ff00ff) * r) & 0xff00ff00);
|
||||
#else
|
||||
r = (*p1 ) & 0xff;
|
||||
g = (*p1 >> 8 ) & 0xff;
|
||||
b = (*p1 >> 16) & 0xff;
|
||||
|
||||
rr = (*p2 ) & 0xff;
|
||||
gg = (*p2 >> 8 ) & 0xff;
|
||||
bb = (*p2 >> 16) & 0xff;
|
||||
|
||||
tmp = (r - rr) * a;
|
||||
nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (g - gg) * a;
|
||||
ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (b - bb) * a;
|
||||
nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
*p2 = ((nb & 0xff) << 16) | ((ng & 0xff) << 8) | (nr & 0xff);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
*p2 = *p1;
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __BLEND
|
||||
#define __BLEND 1
|
||||
void
|
||||
BlendRGBAToRGBA(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
|
||||
int w, int h);
|
||||
#endif
|
|
@ -0,0 +1,298 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "common.h"
|
||||
#include "color.h"
|
||||
|
||||
/* FIXME: DATA32 must become DATA8 */
|
||||
DATA8 _dither_color_lut[256];
|
||||
DATA8 _pal_type = 0;
|
||||
|
||||
void
|
||||
AllocColorTable(Display *d, Colormap cmap)
|
||||
{
|
||||
if (AllocColors332(d, cmap))
|
||||
return;
|
||||
if (AllocColors232(d, cmap))
|
||||
return;
|
||||
if (AllocColors222(d, cmap))
|
||||
return;
|
||||
if (AllocColors221(d, cmap))
|
||||
return;
|
||||
if (AllocColors121(d, cmap))
|
||||
return;
|
||||
if (AllocColors111(d, cmap))
|
||||
return;
|
||||
if (AllocColors1(d, cmap))
|
||||
return;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors332(Display *d, Colormap cmap)
|
||||
{
|
||||
int r, g, b, i = 0;
|
||||
|
||||
for (r = 0; r < 8; r++)
|
||||
{
|
||||
for (g = 0; g < 8; g++)
|
||||
{
|
||||
for (b = 0; b < 4; b++)
|
||||
{
|
||||
XColor xcl;
|
||||
int val;
|
||||
|
||||
val = (r << 5) | (r << 2) | (r >> 1);
|
||||
xcl.red = (unsigned short)((val << 8) | (val));
|
||||
val = (g << 5) | (g << 2) | (g >> 1);
|
||||
xcl.green = (unsigned short)((val << 8) | (val));
|
||||
val = (b << 6) | (b << 4) | (b << 2) | (b);
|
||||
xcl.blue = (unsigned short)((val << 8) | (val));
|
||||
if (!XAllocColor(d, cmap, &xcl))
|
||||
{
|
||||
unsigned long pixels[256];
|
||||
int j;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for(j = 0; j < i; j++)
|
||||
pixels[j] = (unsigned long) _dither_color_lut[j];
|
||||
XFreeColors(d, cmap, pixels, i, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_dither_color_lut[i] = xcl.pixel;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pal_type = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors232(Display *d, Colormap cmap)
|
||||
{
|
||||
int r, g, b, i = 0;
|
||||
|
||||
for (r = 0; r < 4; r++)
|
||||
{
|
||||
for (g = 0; g < 8; g++)
|
||||
{
|
||||
for (b = 0; b < 4; b++)
|
||||
{
|
||||
XColor xcl;
|
||||
int val;
|
||||
|
||||
val = (r << 6) | (r << 4) | (r << 2) | (r);
|
||||
xcl.red = (unsigned short)((val << 8) | (val));
|
||||
val = (g << 5) | (g << 2) | (g >> 1);
|
||||
xcl.green = (unsigned short)((val << 8) | (val));
|
||||
val = (b << 6) | (b << 4) | (b << 2) | (b);
|
||||
xcl.blue = (unsigned short)((val << 8) | (val));
|
||||
if (!XAllocColor(d, cmap, &xcl))
|
||||
{
|
||||
unsigned long pixels[256];
|
||||
int j;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for(j = 0; j < i; j++)
|
||||
pixels[j] = (unsigned long) _dither_color_lut[j];
|
||||
XFreeColors(d, cmap, pixels, i, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_dither_color_lut[i] = xcl.pixel;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pal_type = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors222(Display *d, Colormap cmap)
|
||||
{
|
||||
int r, g, b, i = 0;
|
||||
|
||||
for (r = 0; r < 4; r++)
|
||||
{
|
||||
for (g = 0; g < 4; g++)
|
||||
{
|
||||
for (b = 0; b < 4; b++)
|
||||
{
|
||||
XColor xcl;
|
||||
int val;
|
||||
|
||||
val = (r << 6) | (r << 4) | (r << 2) | (r);
|
||||
xcl.red = (unsigned short)((val << 8) | (val));
|
||||
val = (g << 6) | (g << 4) | (g << 2) | (g);
|
||||
xcl.green = (unsigned short)((val << 8) | (val));
|
||||
val = (b << 6) | (b << 4) | (b << 2) | (b);
|
||||
xcl.blue = (unsigned short)((val << 8) | (val));
|
||||
if (!XAllocColor(d, cmap, &xcl))
|
||||
{
|
||||
unsigned long pixels[256];
|
||||
int j;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for(j = 0; j < i; j++)
|
||||
pixels[j] = (unsigned long) _dither_color_lut[j];
|
||||
XFreeColors(d, cmap, pixels, i, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_dither_color_lut[i] = xcl.pixel;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pal_type = 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors221(Display *d, Colormap cmap)
|
||||
{
|
||||
int r, g, b, i = 0;
|
||||
|
||||
for (r = 0; r < 4; r++)
|
||||
{
|
||||
for (g = 0; g < 4; g++)
|
||||
{
|
||||
for (b = 0; b < 2; b++)
|
||||
{
|
||||
XColor xcl;
|
||||
int val;
|
||||
|
||||
val = (r << 6) | (r << 4) | (r << 2) | (r);
|
||||
xcl.red = (unsigned short)((val << 8) | (val));
|
||||
val = (g << 6) | (g << 4) | (g << 2) | (g);
|
||||
xcl.green = (unsigned short)((val << 8) | (val));
|
||||
val = (b << 7) | (b << 6) | (b << 5) | (b << 4) | (b << 3) | (b << 2) | (b << 1) | (b);
|
||||
xcl.blue = (unsigned short)((val << 8) | (val));
|
||||
if (!XAllocColor(d, cmap, &xcl))
|
||||
{
|
||||
unsigned long pixels[256];
|
||||
int j;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for(j = 0; j < i; j++)
|
||||
pixels[j] = (unsigned long) _dither_color_lut[j];
|
||||
XFreeColors(d, cmap, pixels, i, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_dither_color_lut[i] = xcl.pixel;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pal_type = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors121(Display *d, Colormap cmap)
|
||||
{
|
||||
int r, g, b, i = 0;
|
||||
|
||||
for (r = 0; r < 2; r++)
|
||||
{
|
||||
for (g = 0; g < 4; g++)
|
||||
{
|
||||
for (b = 0; b < 2; b++)
|
||||
{
|
||||
XColor xcl;
|
||||
int val;
|
||||
|
||||
val = (r << 7) | (r << 6) | (r << 5) | (r << 4) | (r << 3) | (r << 2) | (r << 1) | (r);
|
||||
xcl.red = (unsigned short)((val << 8) | (val));
|
||||
val = (g << 6) | (g << 4) | (g << 2) | (g);
|
||||
xcl.green = (unsigned short)((val << 8) | (val));
|
||||
val = (b << 7) | (b << 6) | (b << 5) | (b << 4) | (b << 3) | (b << 2) | (b << 1) | (b);
|
||||
xcl.blue = (unsigned short)((val << 8) | (val));
|
||||
if (!XAllocColor(d, cmap, &xcl))
|
||||
{
|
||||
unsigned long pixels[256];
|
||||
int j;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for(j = 0; j < i; j++)
|
||||
pixels[j] = (unsigned long) _dither_color_lut[j];
|
||||
XFreeColors(d, cmap, pixels, i, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_dither_color_lut[i] = xcl.pixel;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pal_type = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors111(Display *d, Colormap cmap)
|
||||
{
|
||||
int r, g, b, i = 0;
|
||||
|
||||
for (r = 0; r < 2; r++)
|
||||
{
|
||||
for (g = 0; g < 2; g++)
|
||||
{
|
||||
for (b = 0; b < 2; b++)
|
||||
{
|
||||
XColor xcl;
|
||||
int val;
|
||||
|
||||
val = (r << 7) | (r << 6) | (r << 5) | (r << 4) | (r << 3) | (r << 2) | (r << 1) | (r);
|
||||
xcl.red = (unsigned short)((val << 8) | (val));
|
||||
val = (g << 7) | (g << 6) | (g << 5) | (g << 4) | (g << 3) | (g << 2) | (g << 1) | (g);
|
||||
xcl.green = (unsigned short)((val << 8) | (val));
|
||||
val = (b << 7) | (b << 6) | (b << 5) | (b << 4) | (b << 3) | (b << 2) | (b << 1) | (b);
|
||||
xcl.blue = (unsigned short)((val << 8) | (val));
|
||||
if (!XAllocColor(d, cmap, &xcl))
|
||||
{
|
||||
unsigned long pixels[256];
|
||||
int j;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for(j = 0; j < i; j++)
|
||||
pixels[j] = (unsigned long) _dither_color_lut[j];
|
||||
XFreeColors(d, cmap, pixels, i, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_dither_color_lut[i] = xcl.pixel;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pal_type = 5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char
|
||||
AllocColors1(Display *d, Colormap cmap)
|
||||
{
|
||||
XColor xcl;
|
||||
|
||||
xcl.red = (unsigned short)(0x0000);
|
||||
xcl.green = (unsigned short)(0x0000);
|
||||
xcl.blue = (unsigned short)(0x0000);
|
||||
XAllocColor(d, cmap, &xcl);
|
||||
_dither_color_lut[0] = xcl.pixel;
|
||||
xcl.red = (unsigned short)(0xffff);
|
||||
xcl.green = (unsigned short)(0xffff);
|
||||
xcl.blue = (unsigned short)(0xffff);
|
||||
XAllocColor(d, cmap, &xcl);
|
||||
_dither_color_lut[1] = xcl.pixel;
|
||||
_pal_type = 6;
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef __COLOR
|
||||
#define __COLOR 1
|
||||
/* FIXME: DATA32 must become DATA8 */
|
||||
extern DATA8 _dither_color_lut[256];
|
||||
extern DATA8 _pal_type;
|
||||
|
||||
void
|
||||
AllocColorTable(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors332(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors232(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors222(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors221(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors121(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors111(Display *d, Colormap cmap);
|
||||
char
|
||||
AllocColors1(Display *d, Colormap cmap);
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __COMMON
|
||||
#define __COMMON 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DATA64 unsigned long long
|
||||
#define DATA32 unsigned int
|
||||
#define DATA16 unsigned short
|
||||
#define DATA8 unsigned char
|
||||
|
||||
#endif
|
|
@ -0,0 +1,311 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include "file.h"
|
||||
|
||||
static void FileFieldWord(char *s, int num, char *wd);
|
||||
|
||||
char *
|
||||
FileExtension(char *file)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = strrchr(file, '.');
|
||||
if (p != NULL)
|
||||
return(p + 1);
|
||||
return("");
|
||||
}
|
||||
|
||||
int
|
||||
FileExists(char *s)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ((!s) || (!*s))
|
||||
return(0);
|
||||
if (stat(s, &st) < 0)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
FileIsFile(char *s)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ((!s) || (!*s))
|
||||
return(0);
|
||||
if (stat(s, &st) < 0)
|
||||
return(0);
|
||||
if (S_ISREG(st.st_mode))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
FileIsDir(char *s)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ((!s) || (!*s))
|
||||
return(0);
|
||||
if (stat(s, &st) < 0)
|
||||
return(0);
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
char **
|
||||
FileDir(char *dir, int *num)
|
||||
{
|
||||
int i, dirlen;
|
||||
int done = 0;
|
||||
DIR *dirp;
|
||||
char **names;
|
||||
struct dirent *dp;
|
||||
|
||||
if ((!dir) || (!*dir))
|
||||
return(0);
|
||||
dirp = opendir(dir);
|
||||
if (!dirp)
|
||||
{
|
||||
*num = 0;
|
||||
return(NULL);
|
||||
}
|
||||
/* count # of entries in dir (worst case) */
|
||||
for (dirlen = 0; (dp = readdir(dirp)) != NULL; dirlen++);
|
||||
if (!dirlen)
|
||||
{
|
||||
closedir(dirp);
|
||||
*num = dirlen;
|
||||
return(NULL);
|
||||
}
|
||||
names = (char **)malloc(dirlen * sizeof(char *));
|
||||
|
||||
if (!names)
|
||||
return(NULL);
|
||||
|
||||
rewinddir(dirp);
|
||||
for (i = 0; i < dirlen;)
|
||||
{
|
||||
dp = readdir(dirp);
|
||||
if (!dp)
|
||||
break;
|
||||
if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
|
||||
{
|
||||
names[i] = strdup(dp->d_name);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < dirlen)
|
||||
dirlen = i; /* dir got shorter... */
|
||||
closedir(dirp);
|
||||
*num = dirlen;
|
||||
/* do a simple bubble sort here to alphanumberic it */
|
||||
while (!done)
|
||||
{
|
||||
done = 1;
|
||||
for (i = 0; i < dirlen - 1; i++)
|
||||
{
|
||||
if (strcmp(names[i], names[i + 1]) > 0)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
tmp = names[i];
|
||||
names[i] = names[i + 1];
|
||||
names[i + 1] = tmp;
|
||||
done = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(names);
|
||||
}
|
||||
|
||||
void
|
||||
FileFreeDirList(char **l, int num)
|
||||
{
|
||||
if (!l)
|
||||
return;
|
||||
while (num--)
|
||||
if (l[num])
|
||||
free(l[num]);
|
||||
free(l);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
FileDel(char *s)
|
||||
{
|
||||
if ((!s) || (!*s))
|
||||
return;
|
||||
unlink(s);
|
||||
return;
|
||||
}
|
||||
|
||||
time_t
|
||||
FileModDate(char *s)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ((!s) || (!*s))
|
||||
return(0);
|
||||
if (!stat(s, &st) < 0)
|
||||
return(0);
|
||||
if (st.st_mtime > st.st_ctime)
|
||||
{
|
||||
return(st.st_mtime);
|
||||
}
|
||||
else
|
||||
return(st.st_ctime);
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *
|
||||
FileHomeDir(int uid)
|
||||
{
|
||||
static int usr_uid = -1;
|
||||
static char *usr_s = NULL;
|
||||
char *s;
|
||||
struct passwd *pwd;
|
||||
|
||||
s = getenv("HOME");
|
||||
if (s)
|
||||
return strdup(s);
|
||||
if (usr_uid < 0)
|
||||
usr_uid = getuid();
|
||||
if ((uid == usr_uid) && (usr_s))
|
||||
{
|
||||
return(strdup(usr_s));
|
||||
}
|
||||
pwd = getpwuid(uid);
|
||||
if (pwd)
|
||||
{
|
||||
s = strdup(pwd->pw_dir);
|
||||
if (uid == usr_uid)
|
||||
usr_s = strdup(s);
|
||||
return(s);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* gets word number [num] in the string [s] and copies it into [wd] */
|
||||
/* wd is NULL terminated. If word [num] does not exist wd = "" */
|
||||
/* NB: this function now handles quotes so for a line: */
|
||||
/* Hello to "Welcome sir - may I Help" Shub Foo */
|
||||
/* Word 1 = Hello */
|
||||
/* Word 2 = to */
|
||||
/* Word 3 = Welcome sir - may I Help */
|
||||
/* Word 4 = Shub */
|
||||
/* word 5 = Foo */
|
||||
|
||||
char *
|
||||
FileField(char *s, int field)
|
||||
{
|
||||
char buf[4096];
|
||||
|
||||
buf[0] = 0;
|
||||
FileFieldWord(s, field + 1, buf);
|
||||
if (buf[0])
|
||||
{
|
||||
if ((!strcmp(buf, "NULL")) ||
|
||||
(!strcmp(buf, "(null)")))
|
||||
return(NULL);
|
||||
return(strdup(buf));
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
FileFieldWord(char *s, int num, char *wd)
|
||||
{
|
||||
char *cur, *start, *end;
|
||||
int count, inword, inquote, len;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
if (!wd)
|
||||
return;
|
||||
*wd = 0;
|
||||
if (num <= 0)
|
||||
return;
|
||||
cur = s;
|
||||
count = 0;
|
||||
inword = 0;
|
||||
inquote = 0;
|
||||
start = NULL;
|
||||
end = NULL;
|
||||
while ((*cur) && (count < num))
|
||||
{
|
||||
if (inword)
|
||||
{
|
||||
if (inquote)
|
||||
{
|
||||
if (*cur == '"')
|
||||
{
|
||||
inquote = 0;
|
||||
inword = 0;
|
||||
end = cur;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isspace(*cur))
|
||||
{
|
||||
end = cur;
|
||||
inword = 0;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isspace(*cur))
|
||||
{
|
||||
if (*cur == '"')
|
||||
{
|
||||
inquote = 1;
|
||||
start = cur + 1;
|
||||
}
|
||||
else
|
||||
start = cur;
|
||||
inword = 1;
|
||||
}
|
||||
}
|
||||
if (count == num)
|
||||
break;
|
||||
cur++;
|
||||
}
|
||||
if (!start)
|
||||
return;
|
||||
if (!end)
|
||||
end = cur;
|
||||
if (end <= start)
|
||||
return;
|
||||
len = (int)(end - start);
|
||||
if (len > 4000)
|
||||
len = 4000;
|
||||
if (len > 0)
|
||||
{
|
||||
strncpy(wd, start, len);
|
||||
wd[len] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __FILE
|
||||
#define __FILE 1
|
||||
char *FileExtension(char *file);
|
||||
int FileExists(char *s);
|
||||
int FileIsFile(char *s);
|
||||
int FileIsDir(char *s);
|
||||
char **FileDir(char *dir, int *num);
|
||||
void FileFreeDirList(char **l, int num);
|
||||
void FileDel(char *s);
|
||||
time_t FileModDate(char *s);
|
||||
char *FileHomeDir(int uid);
|
||||
char *FileField(char *s, int field);
|
||||
#endif
|
|
@ -0,0 +1,537 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include "common.h"
|
||||
#include "grab.h"
|
||||
|
||||
static char _x_err = 0;
|
||||
|
||||
static void
|
||||
Tmp_HandleXError(Display * d, XErrorEvent * ev)
|
||||
{
|
||||
d = NULL;
|
||||
ev = NULL;
|
||||
_x_err = 1;
|
||||
}
|
||||
|
||||
DATA32 *
|
||||
GrabDrawableToRGBA(Display *d, Drawable p, Pixmap m, Visual *v, Colormap cm,
|
||||
int depth, int x, int y, int w, int h, char domask)
|
||||
{
|
||||
XErrorHandler prev_erh = NULL;
|
||||
XWindowAttributes xatt, ratt;
|
||||
char is_pixmap = 0, created_mask = 0, is_shm = 0, is_mshm = 0;
|
||||
int i, pixel, mpixel;
|
||||
int src_x, src_y, src_w, src_h, ow, oh, ox, oy;
|
||||
int width, height, clipx, clipy, inx, iny;
|
||||
XShmSegmentInfo shminfo, mshminfo;
|
||||
XImage *xim = NULL, *mxim = NULL;
|
||||
static char x_does_shm = -1;
|
||||
DATA32 *data, *ptr;
|
||||
DATA8 rtab[256], gtab[256], btab[256];
|
||||
XColor cols[256];
|
||||
|
||||
ox = x;
|
||||
oy = y;
|
||||
ow = w;
|
||||
oh = h;
|
||||
/* FIXME: hmm - need to co-ordinate this with the app */
|
||||
XGrabServer(d);
|
||||
prev_erh = XSetErrorHandler((XErrorHandler) Tmp_HandleXError);
|
||||
_x_err = 0;
|
||||
/* lets see if its a pixmap or not */
|
||||
XGetWindowAttributes(d, p, &xatt);
|
||||
XSync(d, False);
|
||||
if (_x_err)
|
||||
is_pixmap = 1;
|
||||
/* reset our error handler */
|
||||
XSetErrorHandler((XErrorHandler) prev_erh);
|
||||
if (is_pixmap)
|
||||
{
|
||||
Window dw;
|
||||
|
||||
XGetGeometry(d, p, &dw, &src_x, &src_y,
|
||||
(unsigned int *)&src_w, (unsigned int *)&src_h,
|
||||
(unsigned int *)&src_x, (unsigned int *)&xatt.depth);
|
||||
src_x = 0;
|
||||
src_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Window dw;
|
||||
XGetWindowAttributes(d, xatt.root, &ratt);
|
||||
XTranslateCoordinates(d, p, xatt.root, 0, 0, &src_x, &src_y, &dw);
|
||||
if ((xatt.map_state != IsViewable) &&
|
||||
(xatt.backing_store == NotUseful))
|
||||
{
|
||||
XUngrabServer(d);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* clip to the drawable tree and screen */
|
||||
clipx = 0;
|
||||
clipy = 0;
|
||||
width = xatt.width - x;
|
||||
height = xatt.height - y;
|
||||
if (width > w)
|
||||
width = w;
|
||||
if (height > h)
|
||||
height = h;
|
||||
|
||||
if (!is_pixmap)
|
||||
{
|
||||
if ((src_x + x + width) > ratt.width)
|
||||
width = ratt.width - (src_x + x);
|
||||
if ((src_y + y + height) > ratt.height)
|
||||
height = ratt.height - (src_y + y);
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
clipx = -x;
|
||||
width += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
clipy = -y;
|
||||
height += y;
|
||||
y = 0;
|
||||
}
|
||||
if (!is_pixmap)
|
||||
{
|
||||
if ((src_x + x) < 0)
|
||||
{
|
||||
clipx -= (src_x + x);
|
||||
width += (src_x + x);
|
||||
x = -src_x;
|
||||
}
|
||||
if ((src_y + y) < 0)
|
||||
{
|
||||
clipy -= (src_y + y);
|
||||
height += (src_y + y);
|
||||
y = -src_y;
|
||||
}
|
||||
}
|
||||
if ((width <= 0) || (height <= 0))
|
||||
{
|
||||
XUngrabServer(d);
|
||||
return NULL;
|
||||
}
|
||||
w = width;
|
||||
h = height;
|
||||
if ((!is_pixmap) && (domask) && (!m))
|
||||
{
|
||||
int ord, rect_no = 0;
|
||||
XRectangle *r = NULL;
|
||||
|
||||
r = XShapeGetRectangles(d, p, ShapeBounding, &rect_no, &ord);
|
||||
if (r)
|
||||
{
|
||||
if (!((rect_no == 1) &&
|
||||
(r[0].x == 0) && (r[0].y == 0) &&
|
||||
(r[0].width == xatt.width) && (r[0].height == xatt.height)))
|
||||
{
|
||||
XGCValues gcv;
|
||||
GC gc;
|
||||
|
||||
created_mask = 1;
|
||||
m = XCreatePixmap(d, p, w, h, 1);
|
||||
gcv.foreground = 0;
|
||||
gc = XCreateGC(d, m, GCForeground, &gcv);
|
||||
XFillRectangle(d, m, gc, 0, 0, w, h);
|
||||
XSetForeground(d, gc, 1);
|
||||
for (i = 0; i < rect_no; i++)
|
||||
XFillRectangle(d, m, gc,
|
||||
r[i].x - x, r[i].y - y,
|
||||
r[i].width, r[i].height);
|
||||
XFreeGC(d, gc);
|
||||
}
|
||||
XFree(r);
|
||||
}
|
||||
}
|
||||
/* Create an Ximage (shared or not) */
|
||||
if (x_does_shm < 0)
|
||||
{
|
||||
if (XShmQueryExtension(d))
|
||||
x_does_shm = 1;
|
||||
else
|
||||
x_does_shm = 0;
|
||||
}
|
||||
prev_erh = XSetErrorHandler((XErrorHandler) Tmp_HandleXError);
|
||||
_x_err = 0;
|
||||
if (x_does_shm)
|
||||
{
|
||||
xim = XShmCreateImage(d, v, xatt.depth, ZPixmap, NULL,
|
||||
&shminfo, w, h);
|
||||
if (!xim)
|
||||
xim = XGetImage(d, p, x, y, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
else
|
||||
{
|
||||
XSync(d, False);
|
||||
if (_x_err)
|
||||
{
|
||||
XDestroyImage(xim);
|
||||
xim = XGetImage(d, p, x, y, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
_x_err = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line *
|
||||
xim->height, IPC_CREAT | 0666);
|
||||
if (shminfo.shmid < 0)
|
||||
{
|
||||
XDestroyImage(xim);
|
||||
xim = XGetImage(d, p, x, y, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
shminfo.shmaddr = xim->data = shmat(shminfo.shmid, 0, 0);
|
||||
if (xim->data != (char *)-1)
|
||||
{
|
||||
shminfo.readOnly = False;
|
||||
XShmAttach(d, &shminfo);
|
||||
is_shm = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
XDestroyImage(xim);
|
||||
xim = XGetImage(d, p, x, y, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
xim = XGetImage(d, p, x, y, w, h, 0xffffffff, ZPixmap);
|
||||
if (is_shm)
|
||||
{
|
||||
XShmGetImage(d, p, xim, x, y, 0xffffffff);
|
||||
XSync(d, False);
|
||||
if (_x_err)
|
||||
{
|
||||
shmdt(shminfo.shmaddr);
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
XDestroyImage(xim);
|
||||
xim = XGetImage(d, p, x, y, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
is_shm = 0;
|
||||
}
|
||||
}
|
||||
XSetErrorHandler((XErrorHandler) prev_erh);
|
||||
if ((m) && (domask))
|
||||
{
|
||||
prev_erh = XSetErrorHandler((XErrorHandler) Tmp_HandleXError);
|
||||
_x_err = 0;
|
||||
if (x_does_shm)
|
||||
{
|
||||
mxim = XShmCreateImage(d, v, 1, ZPixmap, NULL,
|
||||
&mshminfo, w, h);
|
||||
if (!mxim)
|
||||
mxim = XGetImage(d, p, 0, 0, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
else
|
||||
{
|
||||
XSync(d, False);
|
||||
if (_x_err)
|
||||
{
|
||||
XDestroyImage(mxim);
|
||||
xim = XGetImage(d, p, 0, 0, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
_x_err = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mshminfo.shmid = shmget(IPC_PRIVATE,
|
||||
mxim->bytes_per_line *
|
||||
mxim->height, IPC_CREAT | 0666);
|
||||
if (mshminfo.shmid < 0)
|
||||
{
|
||||
XDestroyImage(mxim);
|
||||
mxim = XGetImage(d, p, 0, 0, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
mshminfo.shmaddr = xim->data =
|
||||
shmat(mshminfo.shmid, 0, 0);
|
||||
if (mxim->data != (char *)-1)
|
||||
{
|
||||
mshminfo.readOnly = False;
|
||||
XShmAttach(d, &mshminfo);
|
||||
is_mshm = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
shmctl(mshminfo.shmid, IPC_RMID, 0);
|
||||
XDestroyImage(mxim);
|
||||
mxim = XGetImage(d, p, x, y, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
mxim = XGetImage(d, m, 0, 0, w, h, 0xffffffff, ZPixmap);
|
||||
if (is_mshm)
|
||||
{
|
||||
XShmGetImage(d, p, mxim, 0, 0, 0xffffffff);
|
||||
XSync(d, False);
|
||||
if (_x_err)
|
||||
{
|
||||
shmdt(mshminfo.shmaddr);
|
||||
shmctl(mshminfo.shmid, IPC_RMID, 0);
|
||||
XDestroyImage(mxim);
|
||||
mxim = XGetImage(d, p, 0, 0, w, h,
|
||||
0xffffffff, ZPixmap);
|
||||
is_mshm = 0;
|
||||
}
|
||||
XSetErrorHandler((XErrorHandler) prev_erh);
|
||||
}
|
||||
}
|
||||
if ((is_shm) || (is_mshm))
|
||||
{
|
||||
XSync(d, False);
|
||||
XUngrabServer(d);
|
||||
XSync(d, False);
|
||||
}
|
||||
else
|
||||
XUngrabServer(d);
|
||||
|
||||
if ((xatt.depth == 1) && (!cm) && (is_pixmap))
|
||||
{
|
||||
rtab[0] = 0;
|
||||
gtab[0] = 0;
|
||||
btab[0] = 0;
|
||||
rtab[1] = 255;
|
||||
gtab[1] = 255;
|
||||
btab[1] = 255;
|
||||
}
|
||||
else if (xatt.depth <= 8)
|
||||
{
|
||||
if ((!is_pixmap) && (!cm))
|
||||
{
|
||||
cm = xatt.colormap;
|
||||
if (cm == None)
|
||||
cm = ratt.colormap;
|
||||
}
|
||||
else
|
||||
cm = ratt.colormap;
|
||||
|
||||
for (i = 0; i < (1 << xatt.depth); i++)
|
||||
{
|
||||
cols[i].pixel = i;
|
||||
cols[i].flags = DoRed | DoGreen | DoBlue;
|
||||
}
|
||||
XQueryColors(d, cm, cols, 1 << xatt.depth);
|
||||
for (i = 0; i < (1 << xatt.depth); i++)
|
||||
{
|
||||
rtab[i] = cols[i].red >> 8;
|
||||
gtab[i] = cols[i].green >> 8;
|
||||
btab[i] = cols[i].blue >> 8;
|
||||
}
|
||||
}
|
||||
data = malloc(ow * oh * sizeof(DATA32));
|
||||
if (data)
|
||||
{
|
||||
inx = x - ox;
|
||||
iny = y - oy;
|
||||
/* go thru the XImage and convert */
|
||||
switch (depth)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
if (mxim)
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
mpixel = XGetPixel(mxim, x, y);
|
||||
*ptr++ = (0xff000000 >> (mpixel << 31)) |
|
||||
(btab[pixel & 0xff] << 16) |
|
||||
(gtab[pixel & 0xff] << 8) |
|
||||
(rtab[pixel & 0xff]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
*ptr++ = 0xff000000 |
|
||||
(btab[pixel & 0xff] << 16) |
|
||||
(gtab[pixel & 0xff] << 8) |
|
||||
(rtab[pixel & 0xff]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if (mxim)
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
DATA8 r, g, b;
|
||||
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
r = (pixel >> 8) & 0xf8;
|
||||
g = (pixel >> 3) & 0xfc;
|
||||
b = (pixel << 3) & 0xf8;
|
||||
mpixel = XGetPixel(mxim, x, y);
|
||||
*ptr++ = (0xff000000 >> (mpixel << 31)) |
|
||||
(b << 16) |
|
||||
(g << 8) |
|
||||
(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
DATA8 r, g, b;
|
||||
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
r = (pixel >> 8) & 0xf8;
|
||||
g = (pixel >> 3) & 0xfc;
|
||||
b = (pixel << 3) & 0xf8;
|
||||
*ptr++ = 0xff000000 |
|
||||
(b << 16) |
|
||||
(g << 8) |
|
||||
(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
if (mxim)
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
DATA8 r, g, b;
|
||||
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
r = (pixel >> 7) & 0xf8;
|
||||
g = (pixel >> 2) & 0xf8;
|
||||
b = (pixel << 3) & 0xf8;
|
||||
mpixel = XGetPixel(mxim, x, y);
|
||||
*ptr++ = (0xff000000 >> (mpixel << 31)) |
|
||||
(b << 16) |
|
||||
(g << 8) |
|
||||
(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
DATA8 r, g, b;
|
||||
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
r = (pixel >> 7) & 0xf8;
|
||||
g = (pixel >> 2) & 0xf8;
|
||||
b = (pixel << 3) & 0xf8;
|
||||
*ptr++ = 0xff000000 |
|
||||
(b << 16) |
|
||||
(g << 8) |
|
||||
(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
if (mxim)
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
mpixel = XGetPixel(mxim, x, y);
|
||||
*ptr++ = (0xff000000 >> (mpixel << 31)) |
|
||||
((pixel & 0x000000ff) << 16) |
|
||||
((pixel & 0x0000ff00)) |
|
||||
((pixel & 0x00ff0000) >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
ptr = data + ((y + iny) * ow) + inx;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixel = XGetPixel(xim, x, y);
|
||||
*ptr++ = 0xff000000 |
|
||||
((pixel & 0x000000ff) << 16) |
|
||||
((pixel & 0x0000ff00)) |
|
||||
((pixel & 0x00ff0000) >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* destroy the Ximage */
|
||||
if (is_shm)
|
||||
{
|
||||
XSync(d, False);
|
||||
XShmDetach(d, &shminfo);
|
||||
shmdt(shminfo.shmaddr);
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
}
|
||||
if ((is_mshm) && (mxim))
|
||||
{
|
||||
XShmDetach(d, &mshminfo);
|
||||
shmdt(mshminfo.shmaddr);
|
||||
shmctl(mshminfo.shmid, IPC_RMID, 0);
|
||||
}
|
||||
XDestroyImage(xim);
|
||||
if (created_mask)
|
||||
XFreePixmap(d, m);
|
||||
if (mxim)
|
||||
XDestroyImage(mxim);
|
||||
return data;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __GRAB
|
||||
#define __GRAB 1
|
||||
DATA32 *
|
||||
GrabDrawableToRGBA(Display *d, Drawable p, Pixmap m, Visual *v, Colormap cm,
|
||||
int depth, int x, int y, int w, int h, char domask);
|
||||
#endif
|
|
@ -0,0 +1,679 @@
|
|||
#include "common.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "image.h"
|
||||
#include "file.h"
|
||||
|
||||
static ImlibImage *images = NULL;
|
||||
static ImlibImagePixmap *pixmaps = NULL;
|
||||
static ImlibLoader *loaders = NULL;
|
||||
static int cache_size = 4096 * 1024;
|
||||
|
||||
void
|
||||
SetCacheSize(int size)
|
||||
{
|
||||
cache_size = size;
|
||||
CleanupImageCache();
|
||||
CleanupImagePixmapCache();
|
||||
}
|
||||
|
||||
int
|
||||
GetCacheSize(void)
|
||||
{
|
||||
return cache_size;
|
||||
}
|
||||
|
||||
ImlibImage *
|
||||
ProduceImage(void)
|
||||
{
|
||||
ImlibImage *im;
|
||||
|
||||
im = malloc(sizeof(ImlibImage));
|
||||
im->data = NULL;
|
||||
im->file = NULL;
|
||||
im->moddate = 0;
|
||||
im->flags = F_NONE;
|
||||
im->border.left = 0;
|
||||
im->border.right = 0;
|
||||
im->border.top = 0;
|
||||
im->border.bottom = 0;
|
||||
im->references = 0;
|
||||
im->w = 0;
|
||||
im->h = 0;
|
||||
im->loader = NULL;
|
||||
im->next = NULL;
|
||||
return im;
|
||||
}
|
||||
|
||||
void
|
||||
ConsumeImage(ImlibImage *im)
|
||||
{
|
||||
if (im->file)
|
||||
free(im->file);
|
||||
if (im->data)
|
||||
free(im->data);
|
||||
if (im->format)
|
||||
free(im->format);
|
||||
free(im);
|
||||
}
|
||||
|
||||
ImlibImage *
|
||||
FindCachedImage(char *file)
|
||||
{
|
||||
ImlibImage *im, *previous_im;
|
||||
|
||||
im = images;
|
||||
previous_im = NULL;
|
||||
/* go through the images list */
|
||||
while (im)
|
||||
{
|
||||
/* if the filenames match */
|
||||
if (!strcmp(file, im->file))
|
||||
{
|
||||
/* move the image to the head of the pixmap list */
|
||||
if (previous_im)
|
||||
{
|
||||
previous_im->next = im->next;
|
||||
im->next = images;
|
||||
images = im;
|
||||
}
|
||||
/* return it */
|
||||
return im;
|
||||
}
|
||||
previous_im = im;
|
||||
im = im->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
AddImageToCache(ImlibImage *im)
|
||||
{
|
||||
im->next = images;
|
||||
images = im;
|
||||
}
|
||||
|
||||
void
|
||||
RemoveImageFromCache(ImlibImage *im)
|
||||
{
|
||||
ImlibImage *current_im, *previous_im;
|
||||
|
||||
current_im = images;
|
||||
previous_im = NULL;
|
||||
while (current_im)
|
||||
{
|
||||
if (im == current_im)
|
||||
{
|
||||
if (previous_im)
|
||||
previous_im->next = im->next;
|
||||
else
|
||||
images = im->next;
|
||||
return;
|
||||
}
|
||||
current_im = current_im->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
CurrentCacheSize(void)
|
||||
{
|
||||
ImlibImage *im;
|
||||
ImlibImagePixmap *ip;
|
||||
int current_cache = 0;
|
||||
|
||||
im = images;
|
||||
while(im)
|
||||
{
|
||||
if (im->references == 0)
|
||||
{
|
||||
if (!(IMAGE_IS_VALID(im)))
|
||||
{
|
||||
RemoveImageFromCache(im);
|
||||
ConsumeImage(im);
|
||||
}
|
||||
else
|
||||
current_cache += im->w * im->h * sizeof(DATA32);
|
||||
}
|
||||
im = im->next;
|
||||
}
|
||||
ip = pixmaps;
|
||||
while(ip)
|
||||
{
|
||||
if (ip->references == 0)
|
||||
{
|
||||
if (!(IMAGE_IS_VALID(ip->image)))
|
||||
{
|
||||
RemoveImagePixmapFromCache(ip);
|
||||
ConsumeImagePixmap(ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ip->pixmap)
|
||||
{
|
||||
if (ip->depth < 8)
|
||||
current_cache += ip->w * ip->h * (ip->depth / 8);
|
||||
else if (ip->depth == 8)
|
||||
current_cache += ip->w * ip->h;
|
||||
else if (ip->depth <= 16)
|
||||
current_cache += ip->w * ip->h * 2;
|
||||
else if (ip->depth <= 32)
|
||||
current_cache += ip->w * ip->h * 4;
|
||||
}
|
||||
if (ip->mask)
|
||||
current_cache += ip->w * ip->h / 8;
|
||||
}
|
||||
}
|
||||
ip = ip->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CleanupImageCache(void)
|
||||
{
|
||||
ImlibImage *im, *im_last;
|
||||
int current_cache;
|
||||
char operation = 1;
|
||||
|
||||
current_cache = CurrentCacheSize();
|
||||
while ((current_cache > cache_size) || (operation));
|
||||
{
|
||||
im_last = NULL;
|
||||
operation = 0;
|
||||
im = images;
|
||||
while(im)
|
||||
{
|
||||
if (im->references <= 0)
|
||||
im_last = im;
|
||||
im = im->next;
|
||||
}
|
||||
if (im_last)
|
||||
{
|
||||
RemoveImageFromCache(im_last);
|
||||
ConsumeImage(im_last);
|
||||
operation = 1;
|
||||
}
|
||||
current_cache = CurrentCacheSize();
|
||||
}
|
||||
}
|
||||
|
||||
ImlibImagePixmap *
|
||||
ProduceImagePixmap(void)
|
||||
{
|
||||
ImlibImagePixmap *ip;
|
||||
|
||||
ip = malloc(sizeof(ImlibImagePixmap));
|
||||
ip->w = 0;
|
||||
ip->h = 0;
|
||||
ip->pixmap = 0;
|
||||
ip->mask = 0;
|
||||
ip->display = NULL;
|
||||
ip->visual = NULL;
|
||||
ip->depth = 0;
|
||||
ip->mode_count = 0;
|
||||
ip->image = NULL;
|
||||
ip->references = 0;
|
||||
ip->next = NULL;
|
||||
return ip;
|
||||
}
|
||||
|
||||
void
|
||||
ConsumeImagePixmap(ImlibImagePixmap *ip)
|
||||
{
|
||||
if (ip->pixmap)
|
||||
XFreePixmap(ip->display, ip->pixmap);
|
||||
if (ip->mask)
|
||||
XFreePixmap(ip->display, ip->mask);
|
||||
free(ip);
|
||||
}
|
||||
|
||||
ImlibImagePixmap *
|
||||
FindCachedImagePixmap(ImlibImage *im, int w, int h, Display *d, Visual *v,
|
||||
int depth, int mode_count)
|
||||
{
|
||||
ImlibImagePixmap *ip, *previous_ip;
|
||||
|
||||
ip = pixmaps;
|
||||
previous_ip = NULL;
|
||||
/* go through the pixmap list */
|
||||
while (ip)
|
||||
{
|
||||
/* if all the pixmap attributes match */
|
||||
if ((ip->w == w) && (ip->h == h) && (ip->depth == depth) &&
|
||||
(ip->visual == v) && (ip->display == d) &&
|
||||
(ip->mode_count == mode_count))
|
||||
{
|
||||
/* move the pixmap to the head of the pixmap list */
|
||||
if (previous_ip)
|
||||
{
|
||||
previous_ip->next = ip->next;
|
||||
ip->next = pixmaps;
|
||||
pixmaps = ip;
|
||||
}
|
||||
/* return it */
|
||||
return ip;
|
||||
}
|
||||
previous_ip = ip;
|
||||
ip = ip->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
AddImagePixmapToCache(ImlibImagePixmap *ip)
|
||||
{
|
||||
ip->next = pixmaps;
|
||||
pixmaps = ip;
|
||||
}
|
||||
|
||||
void
|
||||
RemoveImagePixmapFromCache(ImlibImagePixmap *ip)
|
||||
{
|
||||
ImlibImagePixmap *current_ip, *previous_ip;
|
||||
|
||||
current_ip = pixmaps;
|
||||
previous_ip = NULL;
|
||||
while (current_ip)
|
||||
{
|
||||
if (ip == current_ip)
|
||||
{
|
||||
if (previous_ip)
|
||||
previous_ip->next = ip->next;
|
||||
else
|
||||
pixmaps = ip->next;
|
||||
return;
|
||||
}
|
||||
current_ip = current_ip->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CleanupImagePixmapCache()
|
||||
{
|
||||
ImlibImagePixmap *ip, *ip_last;
|
||||
int current_cache;
|
||||
char operation = 1;
|
||||
|
||||
current_cache = CurrentCacheSize();
|
||||
while ((current_cache > cache_size) || (operation));
|
||||
{
|
||||
ip_last = NULL;
|
||||
operation = 0;
|
||||
ip = pixmaps;
|
||||
while(ip)
|
||||
{
|
||||
if (ip->references <= 0)
|
||||
ip_last = ip;
|
||||
ip = ip->next;
|
||||
}
|
||||
if (ip_last)
|
||||
{
|
||||
RemoveImagePixmapFromCache(ip_last);
|
||||
ConsumeImagePixmap(ip_last);
|
||||
operation = 1;
|
||||
}
|
||||
current_cache = CurrentCacheSize();
|
||||
}
|
||||
}
|
||||
|
||||
ImlibLoader *
|
||||
ProduceLoader(char *file)
|
||||
{
|
||||
ImlibLoader *l;
|
||||
void (*l_formats)(ImlibLoader *l) ;
|
||||
|
||||
l = malloc(sizeof(ImlibLoader));
|
||||
l->num_formats = 0;
|
||||
l->formats = NULL;
|
||||
l->handle = dlopen(file, RTLD_NOW);
|
||||
if (!l->handle)
|
||||
{
|
||||
free(l);
|
||||
return NULL;
|
||||
}
|
||||
l->load = dlsym(l->handle, "load");
|
||||
l->save = dlsym(l->handle, "save");
|
||||
l_formats = dlsym(l->handle, "formats");
|
||||
if ((!(l->load)) || (!(l->save)) || (!(l_formats)))
|
||||
{
|
||||
dlclose(l->handle);
|
||||
free(l);
|
||||
return NULL;
|
||||
}
|
||||
l_formats(l);
|
||||
l->file = strdup(file);
|
||||
l->next = NULL;
|
||||
return l;
|
||||
}
|
||||
|
||||
char **
|
||||
ListLoaders(int *num_ret)
|
||||
{
|
||||
char **list = NULL, **l, s[4096], *home;
|
||||
int num, i, pi = 0;
|
||||
|
||||
*num_ret = 0;
|
||||
home = FileHomeDir(getuid());
|
||||
sprintf(s, "%s/.loaders/image/", home);
|
||||
l = FileDir(s, &num);
|
||||
if (num > 0)
|
||||
{
|
||||
*num_ret += num;
|
||||
list = malloc(sizeof(char *) * *num_ret);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
sprintf(s, "%s/.loaders/image/%s", home, l[i]);
|
||||
list[i] = strdup(s);
|
||||
}
|
||||
pi = i;
|
||||
FileFreeDirList(l, num);
|
||||
}
|
||||
sprintf(s, "/usr/lib/loaders/image/");
|
||||
l = FileDir(s, &num);
|
||||
if (num > 0)
|
||||
{
|
||||
*num_ret += num;
|
||||
list = realloc(list, sizeof(char *) * *num_ret);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
sprintf(s, "/usr/lib/loaders/image/%s", l[i]);
|
||||
list[pi + i] = strdup(s);
|
||||
}
|
||||
FileFreeDirList(l, num);
|
||||
free(home);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
ConsumeLoader(ImlibLoader *l)
|
||||
{
|
||||
if (l->file)
|
||||
free(l->file);
|
||||
if (l->handle)
|
||||
dlclose(l->handle);
|
||||
if (l->formats)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l->num_formats; i++)
|
||||
free(l->formats[i]);
|
||||
free(l->formats);
|
||||
}
|
||||
free(l);
|
||||
}
|
||||
|
||||
void
|
||||
RescanLoaders(void)
|
||||
{
|
||||
static time_t last_scan_time = 0;
|
||||
static time_t last_modified_home_time = 0;
|
||||
static time_t last_modified_system_time = 0;
|
||||
time_t current_time;
|
||||
char s[4096], *home;
|
||||
char do_reload = 0;
|
||||
|
||||
/* dont stat the dir and rescan if we checked in the last 5 seconds */
|
||||
current_time = time(NULL);
|
||||
if ((current_time - last_scan_time) < 5)
|
||||
return;
|
||||
/* ok - was the system loaders dir contents modified ? */
|
||||
last_scan_time = current_time;
|
||||
if (FileIsDir("/usr/lib/loaders/image/"))
|
||||
{
|
||||
current_time = FileModDate("/usr/lib/loaders/image/");
|
||||
if (current_time > last_modified_system_time)
|
||||
{
|
||||
/* yup - set the "do_reload" flag */
|
||||
do_reload = 1;
|
||||
last_modified_system_time = current_time;
|
||||
}
|
||||
}
|
||||
/* ok - was the users own loaders dir contents modified ? */
|
||||
home = FileHomeDir(getuid());
|
||||
sprintf(s, "%s/.loaders/image/", home);
|
||||
free(home);
|
||||
if (FileIsDir(s))
|
||||
{
|
||||
current_time = FileModDate(s);
|
||||
if (current_time > last_modified_home_time)
|
||||
{
|
||||
/* yup - set the "do_reload" flag */
|
||||
do_reload = 1;
|
||||
last_modified_home_time = current_time;
|
||||
}
|
||||
}
|
||||
/* if we dont ned to reload the loaders - get out now */
|
||||
if (!do_reload)
|
||||
return;
|
||||
RemoveAllLoaders();
|
||||
LoadAllLoaders();
|
||||
}
|
||||
|
||||
void
|
||||
RemoveAllLoaders(void)
|
||||
{
|
||||
ImlibLoader *l, *il;
|
||||
|
||||
l = loaders;
|
||||
while(l)
|
||||
{
|
||||
il = l;
|
||||
l = l->next;
|
||||
ConsumeLoader(il);
|
||||
}
|
||||
loaders = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
LoadAllLoaders(void)
|
||||
{
|
||||
int i, num;
|
||||
char **list;
|
||||
|
||||
list = ListLoaders(&num);
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
for (i = num - 1; i >= 0; i--)
|
||||
{
|
||||
ImlibLoader *l;
|
||||
|
||||
l = ProduceLoader(list[i]);
|
||||
if (l)
|
||||
{
|
||||
l->next = loaders;
|
||||
loaders = l;
|
||||
}
|
||||
if (list[i])
|
||||
free(list[i]);
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
|
||||
ImlibLoader *
|
||||
FindBestLoaderForFile(char *file)
|
||||
{
|
||||
char *extension, *lower;
|
||||
ImlibLoader *l = NULL;
|
||||
|
||||
/* use the file extension for a "best guess" as to what loader to try */
|
||||
/* first at any rate */
|
||||
extension = strdup(FileExtension(file));
|
||||
/* change the extensiont o all lwoer case as all "types" are listed as */
|
||||
/* lower case strings fromt he loader that represent all the possible */
|
||||
/* extensions that file format could have */
|
||||
lower = extension;
|
||||
while (*lower)
|
||||
{
|
||||
*lower = tolower(*lower);
|
||||
lower++;
|
||||
}
|
||||
/* go through the loaders - first loader that claims to handle that */
|
||||
/* image type (extension wise) wins as a first guess to use - NOTE */
|
||||
/* this is an OPTIMISATION - it is possible the file has no extension */
|
||||
/* or has an unrecognised one but still is loadable by a loader. */
|
||||
/* if thkis initial loader failes to load the load mechanism will */
|
||||
/* systematically go from most recently used to least recently used */
|
||||
/* loader until one succeeds - or none are left and all have failed */
|
||||
/* and only if all fail does the laod fail. the lao9der that does */
|
||||
/* succeed gets it way tot he head of the list so it's going */
|
||||
/* to be used first next time in this search mechanims - this */
|
||||
/* assumes you tend to laod a few image types and ones generally */
|
||||
/* of the same format */
|
||||
l = loaders;
|
||||
while (l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l->num_formats; i++)
|
||||
{
|
||||
if (!strcmp(l->formats[i], extension))
|
||||
{
|
||||
free(extension);
|
||||
return l;
|
||||
}
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
free(extension);
|
||||
return l;
|
||||
}
|
||||
|
||||
ImlibImage *
|
||||
LoadImage(char *file)
|
||||
{
|
||||
ImlibImage *im;
|
||||
ImlibLoader *best_loader;
|
||||
|
||||
/* see if we alreayd have the image cached */
|
||||
im = FindCachedImage(file);
|
||||
/* if we found a cached image and we shoudl always check that it is */
|
||||
/* accurate to the disk conents if they changed since we last loaded */
|
||||
/* and that it is still a valid image */
|
||||
if ((im) && (IMAGE_IS_VALID(im)) && (IMAGE_ALWAYS_CHECK_DISK(im)))
|
||||
{
|
||||
time_t current_modified_time;
|
||||
|
||||
current_modified_time = FileModDate(file);
|
||||
/* if the file on disk is newer than the cached one */
|
||||
if (current_modified_time > im->moddate)
|
||||
{
|
||||
/* invalidate image */
|
||||
im->flags &= F_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* image is ok to re-use - program is just being stupid loading */
|
||||
/* the same data twice */
|
||||
im->references++;
|
||||
return im;
|
||||
}
|
||||
}
|
||||
/* either image in cache is invalid or we dont even have it in cache */
|
||||
/* so produce a new one and load an image into that */
|
||||
im = ProduceImage();
|
||||
im->file = strdup(file);
|
||||
im->moddate = FileModDate(file);
|
||||
/* ok - just check all our loaders are up to date */
|
||||
RescanLoaders();
|
||||
/* take a guess by extension on the best loader to use */
|
||||
best_loader = FindBestLoaderForFile(file);
|
||||
if (best_loader)
|
||||
best_loader->load(im);
|
||||
/* width is still 0 - the laoder didnt manage to do anything */
|
||||
if (im->w == 0)
|
||||
{
|
||||
ImlibLoader *l, *previous_l = NULL;
|
||||
l = loaders;
|
||||
/* run through all loaders and try load until one succeeds */
|
||||
while ((l) && (im->w == 0))
|
||||
{
|
||||
/* if its not the best loader that alreayd failed - try load */
|
||||
if (l != best_loader)
|
||||
l->load(im);
|
||||
/* if it failed - advance */
|
||||
if (im->w == 0)
|
||||
{
|
||||
previous_l = l;
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
/* if we have a loader then its the loader that succeeded */
|
||||
/* move the successful loader to the head of the list */
|
||||
/* as long as it's not alreayd at the head of the list */
|
||||
if ((l) && (previous_l))
|
||||
{
|
||||
im->loader = l;
|
||||
previous_l->next = l->next;
|
||||
l->next = loaders;
|
||||
loaders = l;
|
||||
}
|
||||
}
|
||||
else
|
||||
im->loader = best_loader;
|
||||
/* all loaders have been tried and they all failed. free the skeleton */
|
||||
/* image struct we had and return NULL */
|
||||
if (im->w == 0)
|
||||
{
|
||||
ConsumeImage(im);
|
||||
return NULL;
|
||||
}
|
||||
#if 0
|
||||
/* FIXME: need to turn this png loading function into a loader andf then */
|
||||
/* remove the below stuff */
|
||||
im->data = RGBA_Load(file, &(im->w), &(im->h));
|
||||
im->flags = F_HAS_ALPHA;
|
||||
#endif
|
||||
|
||||
|
||||
/* the laod succeeded - make sure the image is refernenced then add */
|
||||
/* it to our cache */
|
||||
im->references = 1;
|
||||
AddImageToCache(im);
|
||||
return im;
|
||||
}
|
||||
|
||||
ImlibImagePixmap *
|
||||
FindImlibImagePixmapByID(Display *d, Pixmap p)
|
||||
{
|
||||
ImlibImagePixmap *ip;
|
||||
|
||||
ip = pixmaps;
|
||||
/* go through the pixmap list */
|
||||
while (ip)
|
||||
{
|
||||
/* if all the pixmap ID & Display match */
|
||||
if ((ip->pixmap == p) && (ip->display == d))
|
||||
return ip;
|
||||
ip = ip->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
FreeImage(ImlibImage *im)
|
||||
{
|
||||
if (im->references > 0)
|
||||
{
|
||||
im->references--;
|
||||
CleanupImageCache();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FreePixmap(Display *d, Pixmap p)
|
||||
{
|
||||
ImlibImagePixmap *ip;
|
||||
|
||||
ip = FindImlibImagePixmapByID(d, p);
|
||||
if (ip->references > 0)
|
||||
{
|
||||
ip->references--;
|
||||
CleanupImagePixmapCache();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef __IMAGE
|
||||
# define __IMAGE 1
|
||||
|
||||
typedef enum _iflags Iflags;
|
||||
typedef struct _imlibimage ImlibImage;
|
||||
typedef struct _imlibimagepixmap ImlibImagePixmap;
|
||||
typedef struct _imlibborder ImlibBorder;
|
||||
typedef struct _imlibloader ImlibLoader;
|
||||
|
||||
enum _iflags
|
||||
{
|
||||
F_NONE = 0,
|
||||
F_HAS_ALPHA = (1 << 0),
|
||||
F_UNLOADED = (1 << 1),
|
||||
F_UNCACHEABLE = (1 << 2),
|
||||
F_ALWAYS_CHECK_DISK = (1 << 3),
|
||||
F_INVALID = (1 << 4)
|
||||
};
|
||||
|
||||
struct _imlibborder
|
||||
{
|
||||
int left, right, top, bottom;
|
||||
};
|
||||
|
||||
struct _imlibimage
|
||||
{
|
||||
char *file;
|
||||
int w, h;
|
||||
DATA32 *data;
|
||||
Iflags flags;
|
||||
time_t moddate;
|
||||
ImlibBorder border;
|
||||
int references;
|
||||
ImlibLoader *loader;
|
||||
ImlibImage *next;
|
||||
char *format;
|
||||
};
|
||||
|
||||
struct _imlibimagepixmap
|
||||
{
|
||||
int w, h;
|
||||
Pixmap pixmap, mask;
|
||||
Display *display;
|
||||
Visual *visual;
|
||||
int depth;
|
||||
int mode_count;
|
||||
ImlibImage *image;
|
||||
int references;
|
||||
ImlibImagePixmap *next;
|
||||
};
|
||||
|
||||
struct _imlibloader
|
||||
{
|
||||
char *file;
|
||||
int num_formats;
|
||||
char **formats;
|
||||
void *handle;
|
||||
char (*load)(ImlibImage *im);
|
||||
char (*save)(ImlibImage *im);
|
||||
ImlibLoader *next;
|
||||
};
|
||||
|
||||
void SetCacheSize(int size);
|
||||
int GetCacheSize(void);
|
||||
ImlibImage *ProduceImage(void);
|
||||
void ConsumeImage(ImlibImage *im);
|
||||
ImlibImage *FindCachedImage(char *file);
|
||||
void AddImageToCache(ImlibImage *im);
|
||||
void RemoveImageFromCache(ImlibImage *im);
|
||||
void CleanupImageCache(void);
|
||||
ImlibImagePixmap *ProduceImagePixmap(void);
|
||||
void ConsumeImagePixmap(ImlibImagePixmap *ip);
|
||||
ImlibImagePixmap *FindCachedImagePixmap(ImlibImage *im, int w, int h,
|
||||
Display *d, Visual *v,
|
||||
int depth, int mode_count);
|
||||
void AddImagePixmapToCache(ImlibImagePixmap *ip);
|
||||
void RemoveImagePixmapFromCache(ImlibImagePixmap *ip);
|
||||
void CleanupImagePixmapCache();
|
||||
ImlibLoader *ProduceLoader(char *file);
|
||||
char **ListLoaders(int *num_ret);
|
||||
void ConsumeLoader(ImlibLoader *l);
|
||||
void RescanLoaders(void);
|
||||
void RemoveAllLoaders(void);
|
||||
void LoadAllLoaders(void);
|
||||
ImlibLoader *FindBestLoaderForFile(char *file);
|
||||
ImlibImage *LoadImage(char *file);
|
||||
ImlibImagePixmap *FindImlibImagePixmapByID(Display *d, Pixmap p);
|
||||
void FreeImage(ImlibImage *im);
|
||||
void FreePixmap(Display *d, Pixmap p);
|
||||
|
||||
# define IMAGE_HAS_ALPHA(im) (im->flags & F_HAS_ALPHA)
|
||||
# define IMAGE_IS_UNLOADED(im) (im->flags & F_UNLOADED)
|
||||
# define IMAGE_IS_UNCACHEABLE(im) (im->flags & F_UNCACHEABLE)
|
||||
# define IMAGE_ALWAYS_CHECK_DISK(im) (im->flags & F_ALWAYS_CHECK_DISK)
|
||||
# define IMAGE_IS_VALID(im) (!(im->flags & F_INVALID))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,162 @@
|
|||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "image.h"
|
||||
#include <png.h>
|
||||
|
||||
/* this is a quick sample png loader module... nioce and small isnt it? */
|
||||
|
||||
/* PNG stuff */
|
||||
#define PNG_BYTES_TO_CHECK 4
|
||||
|
||||
static void *
|
||||
_load_PNG (int *ww, int *hh, FILE *f)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
unsigned char *data, **lines;
|
||||
int i, bit_depth, color_type, interlace_type;
|
||||
unsigned char buf[PNG_BYTES_TO_CHECK];
|
||||
int w, h;
|
||||
|
||||
fread(buf, 1, PNG_BYTES_TO_CHECK, f);
|
||||
if (!png_check_sig(buf, PNG_BYTES_TO_CHECK))
|
||||
{
|
||||
rewind(f);
|
||||
return NULL;
|
||||
}
|
||||
rewind(f);
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr)
|
||||
{
|
||||
rewind(f);
|
||||
return NULL;
|
||||
}
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
rewind(f);
|
||||
return NULL;
|
||||
}
|
||||
if (setjmp(png_ptr->jmpbuf))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
rewind(f);
|
||||
return NULL;
|
||||
}
|
||||
png_init_io(png_ptr, f);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)(&w), (png_uint_32 *)(&h),
|
||||
&bit_depth, &color_type, &interlace_type,
|
||||
NULL, NULL);
|
||||
/* Palette -> RGB */
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
png_set_expand(png_ptr);
|
||||
/* 16bit color -> 8bit color */
|
||||
png_set_strip_16(png_ptr);
|
||||
/* pack all pixels to byte boundaires */
|
||||
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);
|
||||
*ww = w;
|
||||
*hh = h;
|
||||
data = malloc(w * h * 4);
|
||||
lines = (unsigned char **)malloc(h * sizeof(unsigned char *));
|
||||
for (i = 0; i < h; i++)
|
||||
lines[i] = data + (i * w * 4);
|
||||
png_read_image(png_ptr, lines);
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
free(lines);
|
||||
return data;
|
||||
}
|
||||
|
||||
DATA32 *
|
||||
RGBA_Load(char *file, int *w, int *h)
|
||||
{
|
||||
FILE *f;
|
||||
DATA32 *data;
|
||||
|
||||
f = fopen(file, "r");
|
||||
data = (DATA32 *)_load_PNG(w, h, f);
|
||||
fclose(f);
|
||||
return data;
|
||||
}
|
||||
|
||||
char
|
||||
load (ImlibImage *im)
|
||||
{
|
||||
int w, h;
|
||||
DATA32 *data;
|
||||
|
||||
/* alreayd data in this image - dont load it again */
|
||||
if (im->data)
|
||||
return 0;
|
||||
/* ok - this is not 100% right. */
|
||||
/* what I SHOULD be doing is checking the im->loader value - if it's */
|
||||
/* set and im->data is NULL - then I do the SECOND loading phase. */
|
||||
/* this Is optional - but an OPTIMISED loader (like all loaders should */
|
||||
/* if the format allows it) has 2 loading phases. the first time the */
|
||||
/* loader is called If it can withotu performance penalty, read the */
|
||||
/* image header - glean ingormation like width, height, if the image */
|
||||
/* has an alpha channel or not - etc. If this information can be gathered */
|
||||
/* now without haveing to also decode the image data, and if it is */
|
||||
/* possible for the image data to later in a second load / phase, to be */
|
||||
/* loaded separately withotu significant penalty, then the loader */
|
||||
/* shoudl delay imge data decoding until it is actually needed in the */
|
||||
/* second load phase. if it is unable to do this, or the author does */
|
||||
/* not have time to do it properly, then ALL data, including image data */
|
||||
/* should be decoded on the first phase. The loader, if it does this */
|
||||
/* shoudl ignore the image laod if the data memebr is not NULL */
|
||||
/* the below code for now just does a one phase load */
|
||||
data = RGBA_Load(im->file, &w, &h);
|
||||
if (data)
|
||||
{
|
||||
im->data = data;
|
||||
im->flags = F_HAS_ALPHA;
|
||||
/* setting the width to somthign > 0 means you managed to load */
|
||||
/* the image */
|
||||
im->w = w;
|
||||
im->h = h;
|
||||
/* set the format string member to the lower-case full extension */
|
||||
/* name for the format - so example names would be: */
|
||||
/* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */
|
||||
im->format = strdup("png");
|
||||
/* success - retrun 1 */
|
||||
return 1;
|
||||
}
|
||||
/* failure to load... return 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
char
|
||||
save (ImlibImage *im)
|
||||
{
|
||||
/* if we cant do this - just return 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fills the ImlibLoader struct with a strign array of format file */
|
||||
/* extensions this loader can load. eg: */
|
||||
/* loader->formats = { "jpeg", "jpg"}; */
|
||||
/* giving permutations is a good idea. case sensitivity is irrelevant */
|
||||
/* your laoder CAN load more than one format if it likes - like: */
|
||||
/* loader->formats = { "gif", "png", "jpeg", "jpg"} */
|
||||
/* if it can load those formats. */
|
||||
void
|
||||
formats (ImlibLoader *l)
|
||||
{
|
||||
char *list_formats[] =
|
||||
{ "png" };
|
||||
int num_formats = 1;
|
||||
int i;
|
||||
|
||||
l->formats = malloc(sizeof(char *) * num_formats);
|
||||
for (i = 0; i < num_formats; i++)
|
||||
l->formats[i] = strdup(list_formats[i]);
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xos.h>
|
||||
#include <sys/time.h>
|
||||
#include "common.h"
|
||||
#include "image.h"
|
||||
#include "rend.h"
|
||||
#include "rgba.h"
|
||||
|
||||
|
||||
Display *disp;
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
Window win;
|
||||
int i, j;
|
||||
ImlibImage *im;
|
||||
Visual *vis;
|
||||
int depth;
|
||||
int sec1, usec1, sec2, usec2;
|
||||
int pixels = 0;
|
||||
struct timeval timev;
|
||||
double sec;
|
||||
char *file;
|
||||
|
||||
int root = 0;
|
||||
int scale = 0;
|
||||
int w = -1;
|
||||
int h = -1;
|
||||
int aa = 0;
|
||||
int dith = 0;
|
||||
int loop = 1;
|
||||
int blend = 0;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-root"))
|
||||
root = 1;
|
||||
else if (!strcmp(argv[i], "-smooth"))
|
||||
aa = 1;
|
||||
else if (!strcmp(argv[i], "-blend"))
|
||||
blend = 1;
|
||||
else if (!strcmp(argv[i], "-dither"))
|
||||
dith = 1;
|
||||
else if (!strcmp(argv[i], "-scale"))
|
||||
scale = 1;
|
||||
else if (!strcmp(argv[i], "-noloop"))
|
||||
loop = 0;
|
||||
else if (!strcmp(argv[i], "-size"))
|
||||
{
|
||||
i++;
|
||||
w = atoi(argv[i++]);
|
||||
h = atoi(argv[i]);
|
||||
}
|
||||
else
|
||||
file = argv[i];
|
||||
}
|
||||
printf("init\n");
|
||||
RGBA_init();
|
||||
disp = XOpenDisplay(NULL);
|
||||
printf("load\n");
|
||||
im = LoadImage(file);
|
||||
if (!im)
|
||||
printf("load fialed\n");
|
||||
if (w < 0)
|
||||
{
|
||||
w = im->w;
|
||||
h = im->h;
|
||||
}
|
||||
if (root)
|
||||
win = DefaultRootWindow(disp);
|
||||
else
|
||||
{
|
||||
win = XCreateSimpleWindow(disp, DefaultRootWindow(disp), 0, 0, w, h, 0, 0, 0);
|
||||
XMapWindow(disp, win);
|
||||
}
|
||||
if (scale)
|
||||
{
|
||||
Window d;
|
||||
int dd;
|
||||
|
||||
XGetGeometry(disp, win, &d, &dd, &dd, &w, &h, &dd, &dd);
|
||||
}
|
||||
vis = DefaultVisual(disp, DefaultScreen(disp));
|
||||
depth = DefaultDepth(disp, DefaultScreen(disp));
|
||||
if (depth == 8)
|
||||
AllocColorTable(disp, DefaultColormap(disp, DefaultScreen(disp)));
|
||||
XSync(disp, False);
|
||||
printf("rend\n");
|
||||
gettimeofday(&timev,NULL);
|
||||
sec1=(int)timev.tv_sec; /* and stores it so we can time outselves */
|
||||
usec1=(int)timev.tv_usec; /* we will use this to vary speed of rot */
|
||||
SetMaxXImageCount(disp, 5);
|
||||
if (loop)
|
||||
{
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
static Pixmap m = 0;
|
||||
|
||||
if (m)
|
||||
XFreePixmap(disp, m);
|
||||
m = 0;
|
||||
/*
|
||||
if (((w - i) > 0) && ((((w - i) * h) / w) > 0))
|
||||
m = XCreatePixmap(disp, win, (w - i), ((w - i) * h) / w, 1);
|
||||
*/ RenderImage(disp, im,
|
||||
win, m,
|
||||
vis,
|
||||
DefaultColormap(disp, DefaultScreen(disp)),
|
||||
depth,
|
||||
0, 0, im->w, im->h,
|
||||
0, 0, w - i, ((w - i) * h) / w,
|
||||
(char)aa, (char)dith, (char)blend, 0
|
||||
);
|
||||
if (m)
|
||||
{
|
||||
XShapeCombineMask(disp, win, ShapeBounding, 0, 0, m, ShapeSet);
|
||||
}
|
||||
pixels += (w - i) * (((w - i) * h) / w);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderImage(disp, im,
|
||||
win, 0,
|
||||
vis,
|
||||
DefaultColormap(disp, DefaultScreen(disp)),
|
||||
depth,
|
||||
0, 0, im->w, im->h,
|
||||
0, 0, w, h,
|
||||
(char)aa, (char)dith, (char)blend, 0
|
||||
);
|
||||
pixels += (w) * (h);
|
||||
}
|
||||
gettimeofday(&timev,NULL);
|
||||
sec2=(int)timev.tv_sec; /* and stores it so we can time outselves */
|
||||
usec2=(int)timev.tv_usec; /* we will use this to vary speed of rot */
|
||||
printf("done\n");
|
||||
i = sec2 - sec1;
|
||||
j = usec2 - usec1;
|
||||
while (j < 0)
|
||||
{
|
||||
i++;
|
||||
j += 1000000;
|
||||
}
|
||||
sec = (double)i + ((double)j / 1000000);
|
||||
printf("%3.3f sec\n", sec);
|
||||
printf("%3.3f Mpixels / sec\n", (double)(pixels) / (sec * 1000000));
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,424 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include "common.h"
|
||||
#include "scale.h"
|
||||
#include "image.h"
|
||||
#include "ximage.h"
|
||||
#include "rend.h"
|
||||
#include "rgba.h"
|
||||
#include "image.h"
|
||||
#include "color.h"
|
||||
#include "grab.h"
|
||||
#include "blend.h"
|
||||
|
||||
/* size of the lines per segment we scale / render at a time */
|
||||
#define LINESIZE 16
|
||||
|
||||
/* useful macro */
|
||||
#define CLIP(x, y, w, h, xx, yy, ww, hh) \
|
||||
if (x < xx) {w += x; x = xx;} \
|
||||
if (y < yy) {h += y; y = xx;} \
|
||||
if ((x + w) > ww) {w = ww - x;} \
|
||||
if ((y + h) > hh) {h = hh - y;}
|
||||
|
||||
void
|
||||
RenderImage(Display *d, ImlibImage *im,
|
||||
Drawable w, Drawable m,
|
||||
Visual *v, Colormap cm, int depth,
|
||||
int sx, int sy, int sw, int sh,
|
||||
int dx, int dy, int dw, int dh,
|
||||
char anitalias, char hiq, char blend, char dither_mask)
|
||||
{
|
||||
XImage *xim, *mxim;
|
||||
DATA32 *buf = NULL, *pointer, *back = NULL;
|
||||
int y, h, hh, jump;
|
||||
static GC gc = 0;
|
||||
static GC gcm = 0;
|
||||
XGCValues gcv;
|
||||
DATA32 **ypoints = NULL;
|
||||
int *xpoints = NULL;
|
||||
int *yapoints = NULL;
|
||||
int *xapoints = NULL;
|
||||
int scw, sch;
|
||||
int psx, psy, psw, psh;
|
||||
char xup = 0, yup = 0;
|
||||
char shm = 0;
|
||||
|
||||
/* dont do anything if we have a 0 widht or height image to render */
|
||||
if ((dw <= 0) || (dh <= 0))
|
||||
return;
|
||||
/* if the input rect size < 0 dont render either */
|
||||
if ((sw <= 0) || (sh <= 0))
|
||||
return;
|
||||
/* if the output is too big (8k arbitary limit here) dont bother */
|
||||
if ((dw > 8192) || (dh > 8192))
|
||||
return;
|
||||
/* clip the source rect to be within the actual image */
|
||||
psx = sx;
|
||||
psy = sy;
|
||||
psw = sw;
|
||||
psh = sh;
|
||||
CLIP(sx, sy, sw, sh, 0, 0, im->w, im->h);
|
||||
/* clip output coords to clipped input coords */
|
||||
if (psx != sx)
|
||||
dx = (dx * sx) / psx;
|
||||
if (psy != sy)
|
||||
dy = (dy * sy) / psy;
|
||||
if (psw != sw)
|
||||
dw = (dw * sw) / psw;
|
||||
if (psh != sh)
|
||||
dh = (dh * sh) / psh;
|
||||
/* do a second check to see if we now have invalid coords */
|
||||
/* dont do anything if we have a 0 widht or height image to render */
|
||||
if ((dw <= 0) || (dh <= 0))
|
||||
return;
|
||||
/* if the input rect size < 0 dont render either */
|
||||
if ((sw <= 0) || (sh <= 0))
|
||||
return;
|
||||
/* if the output is too big (8k arbitary limit here) dont bother */
|
||||
if ((dw > 8192) || (dh > 8192))
|
||||
return;
|
||||
/* calculate the scaling factors of width and height for a whole image */
|
||||
scw = dw * im->w / sw;
|
||||
sch = dh * im->h / sh;
|
||||
/* if we are scaling the image at all make a scaling buffer */
|
||||
if (!((sw == dw) && (sh == dh)))
|
||||
{
|
||||
/* need to calculate ypoitns and xpoints array */
|
||||
ypoints = CalcYPoints(im->data, im->w, im->h, sch, im->border.top, im->border.bottom);
|
||||
if (!ypoints)
|
||||
return;
|
||||
xpoints = CalcXPoints(im->w, scw, im->border.left, im->border.right);
|
||||
if (!xpoints)
|
||||
{
|
||||
free(ypoints);
|
||||
return;
|
||||
}
|
||||
/* calculate aliasing counts */
|
||||
if (anitalias)
|
||||
{
|
||||
yapoints = CalcApoints(im->h, sch, im->border.top, im->border.bottom);
|
||||
if (!yapoints)
|
||||
{
|
||||
free(ypoints);
|
||||
free(xpoints);
|
||||
return;
|
||||
}
|
||||
xapoints = CalcApoints(im->w, scw, im->border.left, im->border.right);
|
||||
if (!xapoints)
|
||||
{
|
||||
free(yapoints);
|
||||
free(ypoints);
|
||||
free(xpoints);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((blend) && (IMAGE_HAS_ALPHA(im)))
|
||||
back = GrabDrawableToRGBA(d, w, 0, v, cm, depth, dx, dy, dw, dh, 0);
|
||||
/* get a new XImage - or get one from the cached list */
|
||||
xim = ProduceXImage(d, v, depth, dw, dh, &shm);
|
||||
if (!xim)
|
||||
{
|
||||
if (anitalias)
|
||||
{
|
||||
free(xapoints);
|
||||
free(yapoints);
|
||||
}
|
||||
free(ypoints);
|
||||
free(xpoints);
|
||||
if (back)
|
||||
free(back);
|
||||
return;
|
||||
}
|
||||
/* do a double check in 24/32bpp */
|
||||
if ((xim->bits_per_pixel == 32) && (depth == 24))
|
||||
depth = 32;
|
||||
if (m)
|
||||
{
|
||||
mxim = ProduceXImage(d, v, 1, dw, dh, &shm);
|
||||
if (!mxim)
|
||||
{
|
||||
ConsumeXImage(d, xim);
|
||||
if (anitalias)
|
||||
{
|
||||
free(xapoints);
|
||||
free(yapoints);
|
||||
}
|
||||
free(ypoints);
|
||||
free(xpoints);
|
||||
if (back)
|
||||
free(back);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* if we are scaling the image at all make a scaling buffer */
|
||||
if (!((sw == dw) && (sh == dh)))
|
||||
{
|
||||
/* allocate a buffer to render scaled RGBA data into */
|
||||
buf = malloc(dw * LINESIZE * sizeof(int));
|
||||
if (!buf)
|
||||
{
|
||||
ConsumeXImage(d, xim);
|
||||
if (m)
|
||||
ConsumeXImage(d, mxim);
|
||||
if (anitalias)
|
||||
{
|
||||
free(xapoints);
|
||||
free(yapoints);
|
||||
}
|
||||
free(ypoints);
|
||||
free(xpoints);
|
||||
if (back)
|
||||
free(back);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* setup h */
|
||||
h = dh;
|
||||
/* set our scaling up in x / y dir flags */
|
||||
if (dw > sw)
|
||||
xup = 1;
|
||||
if (dh > sh)
|
||||
yup = 1;
|
||||
/* scale in LINESIZE Y chunks and convert to depth*/
|
||||
for (y = 0; y < dh; y += LINESIZE)
|
||||
{
|
||||
hh = LINESIZE;
|
||||
if (h < LINESIZE)
|
||||
hh = h;
|
||||
/* if we're scaling it */
|
||||
if (buf)
|
||||
{
|
||||
/* scale the imagedata for this LINESIZE lines chunk of image data */
|
||||
if (anitalias)
|
||||
{
|
||||
if (IMAGE_HAS_ALPHA(im))
|
||||
ScaleAARGBA(ypoints, xpoints, buf, xapoints, yapoints, xup, yup, dx, dy + y, 0, 0, dw, hh, dw, im->w);
|
||||
else
|
||||
ScaleAARGB(ypoints, xpoints, buf, xapoints, yapoints, xup, yup, dx, dy + y, 0, 0, dw, hh, dw, im->w);
|
||||
}
|
||||
else
|
||||
ScaleSampleRGBA(ypoints, xpoints, buf, dx, dy + y, 0, 0, dw, hh, dw);
|
||||
jump = 0;
|
||||
pointer = buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
jump = im->w - sw;
|
||||
pointer = im->data + ((y + sy) * im->w) + sx;
|
||||
}
|
||||
/* if we have a back buffer - we're blending to the bg */
|
||||
if (back)
|
||||
{
|
||||
BlendRGBAToRGBA(pointer, jump, back + (y * dw), 0, dw, hh);
|
||||
pointer = back + (y * dw);
|
||||
jump = 0;
|
||||
}
|
||||
/* once scaled... convert chunk to bit depth into XImage bufer */
|
||||
/* NB - the order here may be random - but I chose it to select most */
|
||||
/* common depths first */
|
||||
if (depth == 16)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB565_dither(pointer, jump,
|
||||
((DATA16 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA16))),
|
||||
(xim->bytes_per_line / sizeof(DATA16)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB565_fast(pointer, jump,
|
||||
((DATA16 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA16))),
|
||||
(xim->bytes_per_line / sizeof(DATA16)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
/* FIXME: need to handle different RGB ordering */
|
||||
else if (depth == 24)
|
||||
{
|
||||
RGBA_to_RGB888_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * xim->bytes_per_line),
|
||||
xim->bytes_per_line - (dw * 3),
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (depth == 32)
|
||||
{
|
||||
RGBA_to_RGB8888_fast(pointer, jump,
|
||||
((DATA32 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA32))),
|
||||
(xim->bytes_per_line / sizeof(DATA32)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (depth == 8)
|
||||
{
|
||||
if (_pal_type == 0)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB332_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB332_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (_pal_type == 1)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB232_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB232_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (_pal_type == 2)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB222_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB222_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (_pal_type == 3)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB221_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB221_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (_pal_type == 4)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB121_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB121_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (_pal_type == 5)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB111_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB111_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
else if (_pal_type == 6)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB1_dither(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB1_fast(pointer, jump,
|
||||
((DATA8 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA8))),
|
||||
(xim->bytes_per_line / sizeof(DATA8)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
}
|
||||
else if (depth == 15)
|
||||
{
|
||||
if (hiq)
|
||||
RGBA_to_RGB555_dither(pointer, jump,
|
||||
((DATA16 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA16))),
|
||||
(xim->bytes_per_line / sizeof(DATA16)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_RGB555_fast(pointer, jump,
|
||||
((DATA16 *)xim->data) + (y * (xim->bytes_per_line / sizeof(DATA16))),
|
||||
(xim->bytes_per_line / sizeof(DATA16)) - dw,
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
if (m)
|
||||
{
|
||||
memset(((DATA8 *)mxim->data) + (y * (mxim->bytes_per_line)),
|
||||
0x0, mxim->bytes_per_line * hh);
|
||||
if (dither_mask)
|
||||
RGBA_to_A1_dither(pointer, jump,
|
||||
((DATA8 *)mxim->data) + (y * (mxim->bytes_per_line)),
|
||||
(mxim->bytes_per_line) - (dw >> 3),
|
||||
dw, hh, dx, dy + y);
|
||||
else
|
||||
RGBA_to_A1_fast(pointer, jump,
|
||||
((DATA8 *)mxim->data) + (y * (mxim->bytes_per_line)),
|
||||
(mxim->bytes_per_line) - (dw >> 3),
|
||||
dw, hh, dx, dy + y);
|
||||
}
|
||||
/* FIXME: have to add code to generate mask if asked for */
|
||||
h -= LINESIZE;
|
||||
}
|
||||
/* free up our buffers and poit tables */
|
||||
if (buf)
|
||||
{
|
||||
free(buf);
|
||||
free(ypoints);
|
||||
free(xpoints);
|
||||
}
|
||||
if (anitalias)
|
||||
{
|
||||
free(yapoints);
|
||||
free(xapoints);
|
||||
}
|
||||
if (back)
|
||||
free(back);
|
||||
/* if we didnt have a gc... create it */
|
||||
if (!gc)
|
||||
{
|
||||
gcv.graphics_exposures = False;
|
||||
gc = XCreateGC(d, w, GCGraphicsExposures, &gcv);
|
||||
}
|
||||
if (m)
|
||||
{
|
||||
if (!gcm)
|
||||
{
|
||||
gcv.graphics_exposures = False;
|
||||
gcm = XCreateGC(d, m, GCGraphicsExposures, &gcv);
|
||||
}
|
||||
/* write the mask */
|
||||
if (shm)
|
||||
/* write shm XImage */
|
||||
XShmPutImage(d, m, gcm, mxim, 0, 0, dx, dy, dw, dh, False);
|
||||
/* write regular XImage */
|
||||
else
|
||||
XPutImage(d, m, gcm, mxim, 0, 0, dx, dy, dw, dh);
|
||||
}
|
||||
/* write the image */
|
||||
if (shm)
|
||||
/* write shm XImage */
|
||||
XShmPutImage(d, w, gc, xim, 0, 0, dx, dy, dw, dh, False);
|
||||
/* write regular XImage */
|
||||
else
|
||||
XPutImage(d, w, gc, xim, 0, 0, dx, dy, dw, dh);
|
||||
/* free the XImage and put onto our free list */
|
||||
/* wait for the write to be done */
|
||||
if (shm)
|
||||
XSync(d, False);
|
||||
ConsumeXImage(d, xim);
|
||||
if (m)
|
||||
ConsumeXImage(d, mxim);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __REND
|
||||
#define __REND 1
|
||||
void
|
||||
RenderImage(Display *d, ImlibImage *im,
|
||||
Drawable w, Drawable m,
|
||||
Visual *v, Colormap cm, int depth,
|
||||
int sx, int sy, int sw, int sh,
|
||||
int dx, int dy, int dw, int dh,
|
||||
char anitalias, char hiq, char blend, char dither_mask);
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
#ifndef __RGBA
|
||||
#define __RGBA 1
|
||||
|
||||
void RGBA_init(void);
|
||||
void RGBA_to_RGB565_fast(DATA32 *src , int src_jump,
|
||||
DATA16 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB565_dither(DATA32 *src , int src_jump,
|
||||
DATA16 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB555_fast(DATA32 *src , int src_jump,
|
||||
DATA16 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB555_dither(DATA32 *src , int src_jump,
|
||||
DATA16 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB332_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB332_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB232_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB232_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB222_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB222_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB221_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB221_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB121_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB121_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB111_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB111_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB1_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB1_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_A1_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_A1_dither(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB8888_fast(DATA32 *src , int src_jump,
|
||||
DATA32 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
void RGBA_to_RGB888_fast(DATA32 *src , int src_jump,
|
||||
DATA8 *dest, int dest_jump,
|
||||
int width, int height, int dx, int dy);
|
||||
#endif
|
|
@ -0,0 +1,872 @@
|
|||
#include "common.h"
|
||||
#include "scale.h"
|
||||
|
||||
#define R_VAL(x) (((x) & 0x000000ff))
|
||||
#define G_VAL(x) (((x) & 0x0000ff00) >> 8)
|
||||
#define B_VAL(x) (((x) & 0x00ff0000) >> 16)
|
||||
#define A_VAL(x) (((x) & 0xff000000) >> 24)
|
||||
#define RGBA_COMPOSE(r, g, b, a) ((a) << 24) | ((b) << 16) | ((g) << 8) | (r)
|
||||
#define INV_XAP (255 - xapoints[x])
|
||||
#define XAP (xapoints[x])
|
||||
#define INV_YAP (255 - yapoints[dyy + y])
|
||||
#define YAP (yapoints[dyy + y])
|
||||
|
||||
DATA32 **
|
||||
CalcYPoints(DATA32 *src, int sw, int sh, int dh, int b1, int b2)
|
||||
{
|
||||
DATA32 **p;
|
||||
int i, j = 0;
|
||||
int val, inc;
|
||||
|
||||
p = malloc(dh * sizeof(DATA32 *));
|
||||
if (dh < (b1 + b2))
|
||||
{
|
||||
if (dh < b1)
|
||||
{
|
||||
b1 = dh;
|
||||
b2 = 0;
|
||||
}
|
||||
else
|
||||
b2 = dh - b1;
|
||||
}
|
||||
val = 0;
|
||||
inc = 1 << 16;
|
||||
for (i = 0; i < b1; i++)
|
||||
{
|
||||
p[j++] = src + ((val >> 16) * sw);
|
||||
val += inc;
|
||||
}
|
||||
if (dh > (b1 + b2))
|
||||
{
|
||||
val = (b1 << 16);
|
||||
inc = ((sh - b1 - b2) << 16) / (dh - b1 - b2);
|
||||
for (i = 0; i < (dh - b1 - b2); i++)
|
||||
{
|
||||
p[j++] = src + ((val >> 16) * sw);
|
||||
val += inc;
|
||||
}
|
||||
}
|
||||
val = (sh - b2) << 16;
|
||||
inc = 1 << 16;
|
||||
for (i = 0; i < b2; i++)
|
||||
{
|
||||
p[j++] = src + ((val >> 16) * sw);
|
||||
val += inc;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int *
|
||||
CalcXPoints(int sw, int dw, int b1, int b2)
|
||||
{
|
||||
int *p, i, j = 0;
|
||||
int val, inc;
|
||||
|
||||
p = malloc(dw * sizeof(int));
|
||||
if (dw < (b1 + b2))
|
||||
{
|
||||
if (dw < b1)
|
||||
{
|
||||
b1 = dw;
|
||||
b2 = 0;
|
||||
}
|
||||
else
|
||||
b2 = dw - b1;
|
||||
}
|
||||
val = 0;
|
||||
inc = 1 << 16;
|
||||
for (i = 0; i < b1; i++)
|
||||
{
|
||||
p[j++] = (val >> 16);
|
||||
val += inc;
|
||||
}
|
||||
if (dw > (b1 + b2))
|
||||
{
|
||||
val = (b1 << 16);
|
||||
inc = ((sw - b1 - b2) << 16) / (dw - b1 - b2);
|
||||
for (i = 0; i < (dw - b1 - b2); i++)
|
||||
{
|
||||
p[j++] = (val >> 16);
|
||||
val += inc;
|
||||
}
|
||||
}
|
||||
val = (sw - b2) << 16;
|
||||
inc = 1 << 16;
|
||||
for (i = 0; i < b2; i++)
|
||||
{
|
||||
p[j++] = (val >> 16);
|
||||
val += inc;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int *
|
||||
CalcApoints(int s, int d, int b1, int b2)
|
||||
{
|
||||
int *p, i, v, j = 0;
|
||||
|
||||
p = malloc(d * sizeof(int));
|
||||
if (d < (b1 + b2))
|
||||
{
|
||||
if (d < b1)
|
||||
{
|
||||
b1 = d;
|
||||
b2 = 0;
|
||||
}
|
||||
else
|
||||
b2 = d - b1;
|
||||
}
|
||||
/* scaling up */
|
||||
if (d > s)
|
||||
{
|
||||
int val, inc;
|
||||
|
||||
for (i = 0; i < b1; i++)
|
||||
p[j++] = 0;
|
||||
if (d > (b1 + b2))
|
||||
{
|
||||
int ss, dd;
|
||||
|
||||
ss = s - b1 - b2;
|
||||
dd = d - b1 - b2;
|
||||
val = 0;
|
||||
inc = (ss << 16) / dd;
|
||||
for (i = 0; i < dd; i++)
|
||||
{
|
||||
p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
|
||||
if (((val >> 16) + b1) >= (s - 1))
|
||||
p[j - 1] = 0;
|
||||
val += inc;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < b2; i++)
|
||||
p[j++] = 0;
|
||||
}
|
||||
/* scaling down */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < b1; i++)
|
||||
p[j++] = 1;
|
||||
if (d > (b1 + b2))
|
||||
{
|
||||
int ss, dd;
|
||||
|
||||
ss = s - b1 - b2;
|
||||
dd = d - b1 - b2;
|
||||
for (i = 0; i < dd; i++)
|
||||
{
|
||||
v = (((i + 1) * ss) / dd) - ((i * ss) / dd);
|
||||
if (v != 1)
|
||||
{
|
||||
if (((((i + 1) * ss) / dd) + b1) >= s)
|
||||
v = s - (((i * ss) / dd) + b1) - 1;
|
||||
p[j++] = v;
|
||||
}
|
||||
else
|
||||
p[j++] = v;
|
||||
if (p[j - 1] < 1)
|
||||
p[j - 1] = 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < b2; i++)
|
||||
p[j++] = 1;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* scale by pixel sampling only */
|
||||
void
|
||||
ScaleSampleRGBA(DATA32 **ypoints, int *xpoints, DATA32 *dest,
|
||||
int dxx, int dyy, int dx, int dy, int dw, int dh, int dow)
|
||||
{
|
||||
DATA32 *sptr, *dptr;
|
||||
int x, y, end;
|
||||
|
||||
/* whats the last pixel ont he line so we stop there */
|
||||
end = dxx + dw;
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* get the pointer to the start of the destination scanline */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
/* calculate the source line we'll scan from */
|
||||
sptr = ypoints[dyy + y];
|
||||
/* go thru the scanline and copy across */
|
||||
for (x = dxx; x < end; x++)
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*/
|
||||
|
||||
/* scale by area sampling */
|
||||
void
|
||||
ScaleAARGBA(DATA32 **ypoints, int *xpoints, DATA32 *dest,
|
||||
int *xapoints, int *yapoints, char xup, char yup,
|
||||
int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow)
|
||||
{
|
||||
DATA32 *sptr, *ssptr, *dptr;
|
||||
int x, y, i, j, end;
|
||||
|
||||
end = dxx + dw;
|
||||
/* scaling up both ways */
|
||||
if ((xup) && (yup))
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0, a = 0;
|
||||
int rr = 0, gg = 0, bb = 0, aa = 0;
|
||||
DATA32 pix;
|
||||
|
||||
if (YAP > 0)
|
||||
{
|
||||
if (XAP > 0)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_XAP;
|
||||
g = G_VAL(pix) * INV_XAP;
|
||||
b = B_VAL(pix) * INV_XAP;
|
||||
a = A_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
r += R_VAL(pix) * XAP;
|
||||
g += G_VAL(pix) * XAP;
|
||||
b += B_VAL(pix) * XAP;
|
||||
a += A_VAL(pix) * XAP;
|
||||
ssptr += sow;
|
||||
pix = ssptr[xpoints[x]];
|
||||
rr = R_VAL(pix) * INV_XAP;
|
||||
gg = G_VAL(pix) * INV_XAP;
|
||||
bb = B_VAL(pix) * INV_XAP;
|
||||
aa = A_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
rr += R_VAL(pix) * XAP;
|
||||
gg += G_VAL(pix) * XAP;
|
||||
bb += B_VAL(pix) * XAP;
|
||||
aa += A_VAL(pix) * XAP;
|
||||
r = ((rr * YAP) + (r * INV_YAP)) >> 16;
|
||||
g = ((gg * YAP) + (g * INV_YAP)) >> 16;
|
||||
b = ((bb * YAP) + (b * INV_YAP)) >> 16;
|
||||
a = ((aa * YAP) + (a * INV_YAP)) >> 16;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_YAP;
|
||||
g = G_VAL(pix) * INV_YAP;
|
||||
b = B_VAL(pix) * INV_YAP;
|
||||
a = A_VAL(pix) * INV_YAP;
|
||||
ssptr += sow;
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix) * YAP;
|
||||
g += G_VAL(pix) * YAP;
|
||||
b += B_VAL(pix) * YAP;
|
||||
a += A_VAL(pix) * YAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
a >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XAP > 0)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_XAP;
|
||||
g = G_VAL(pix) * INV_XAP;
|
||||
b = B_VAL(pix) * INV_XAP;
|
||||
a = A_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
r += R_VAL(pix) * XAP;
|
||||
g += G_VAL(pix) * XAP;
|
||||
b += B_VAL(pix) * XAP;
|
||||
a += A_VAL(pix) * XAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
a >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we're scaling down vertically */
|
||||
else if ((xup) && (!yup))
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0, a = 0;
|
||||
int rr = 0, gg = 0, bb = 0, aa = 0;
|
||||
int count;
|
||||
DATA32 pix;
|
||||
|
||||
if (XAP > 0)
|
||||
{
|
||||
if (YAP > 1)
|
||||
{
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j * sow);
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
a += A_VAL(pix);
|
||||
}
|
||||
count = j;
|
||||
r = r * INV_XAP / count;
|
||||
g = g * INV_XAP / count;
|
||||
b = b * INV_XAP / count;
|
||||
a = a * INV_XAP / count;
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j * sow);
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
rr += R_VAL(pix);
|
||||
gg += G_VAL(pix);
|
||||
bb += B_VAL(pix);
|
||||
aa += A_VAL(pix);
|
||||
}
|
||||
count = j;
|
||||
r = (r + ((rr * XAP) / count)) >> 8;
|
||||
g = (g + ((gg * XAP) / count)) >> 8;
|
||||
b = (b + ((bb * XAP) / count)) >> 8;
|
||||
a = (a + ((aa * XAP) / count)) >> 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_XAP;
|
||||
g = G_VAL(pix) * INV_XAP;
|
||||
b = B_VAL(pix) * INV_XAP;
|
||||
a = A_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
r += R_VAL(pix) * XAP;
|
||||
g += G_VAL(pix) * XAP;
|
||||
b += B_VAL(pix) * XAP;
|
||||
a += A_VAL(pix) * XAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
a >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (YAP > 1)
|
||||
{
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j *sow);
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
a += A_VAL(pix);
|
||||
}
|
||||
count = j;
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
a /= count;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we're scaling down horizontally */
|
||||
else if ((!xup) && (yup))
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0, a = 0;
|
||||
int rr = 0, gg = 0, bb = 0, aa = 0;
|
||||
int count;
|
||||
DATA32 pix;
|
||||
|
||||
if (YAP > 0)
|
||||
{
|
||||
if (XAP > 1)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
a += A_VAL(pix);
|
||||
}
|
||||
count = i;
|
||||
r = r * INV_YAP / count;
|
||||
g = g * INV_YAP / count;
|
||||
b = b * INV_YAP / count;
|
||||
a = a * INV_YAP / count;
|
||||
ssptr = ypoints[dyy + y] + sow;
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
rr += R_VAL(pix);
|
||||
gg += G_VAL(pix);
|
||||
bb += B_VAL(pix);
|
||||
aa += A_VAL(pix);
|
||||
}
|
||||
count = i;
|
||||
r = (r + ((rr * YAP) / count)) >> 8;
|
||||
g = (g + ((gg * YAP) / count)) >> 8;
|
||||
b = (b + ((bb * YAP) / count)) >> 8;
|
||||
a = (a + ((aa * YAP) / count)) >> 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_YAP;
|
||||
g = G_VAL(pix) * INV_YAP;
|
||||
b = B_VAL(pix) * INV_YAP;
|
||||
a = A_VAL(pix) * INV_YAP;
|
||||
ssptr += sow;
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix) * YAP;
|
||||
g += G_VAL(pix) * YAP;
|
||||
b += B_VAL(pix) * YAP;
|
||||
a += A_VAL(pix) * YAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
a >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XAP > 1)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
a += A_VAL(pix);
|
||||
}
|
||||
count = i;
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
a /= count;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we're scaling down horizontally & vertically */
|
||||
else
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0, a = 0;
|
||||
int count;
|
||||
DATA32 pix;
|
||||
|
||||
if ((XAP > 1) || (YAP > 1))
|
||||
{
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j * sow);
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
a += A_VAL(pix);
|
||||
}
|
||||
}
|
||||
count = (i * j);
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
a /= count;
|
||||
pix = RGBA_COMPOSE(r, g, b, a);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* scale by area sampling - IGNORE the ALPHA byte*/
|
||||
void
|
||||
ScaleAARGB(DATA32 **ypoints, int *xpoints, DATA32 *dest,
|
||||
int *xapoints, int *yapoints, char xup, char yup,
|
||||
int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow)
|
||||
{
|
||||
DATA32 *sptr, *ssptr, *dptr;
|
||||
int x, y, i, j, end;
|
||||
|
||||
end = dxx + dw;
|
||||
/* scaling up both ways */
|
||||
if ((xup) && (yup))
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0;
|
||||
int rr = 0, gg = 0, bb = 0;
|
||||
DATA32 pix;
|
||||
|
||||
if (YAP > 0)
|
||||
{
|
||||
if (XAP > 0)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_XAP;
|
||||
g = G_VAL(pix) * INV_XAP;
|
||||
b = B_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
r += R_VAL(pix) * XAP;
|
||||
g += G_VAL(pix) * XAP;
|
||||
b += B_VAL(pix) * XAP;
|
||||
ssptr += sow;
|
||||
pix = ssptr[xpoints[x]];
|
||||
rr = R_VAL(pix) * INV_XAP;
|
||||
gg = G_VAL(pix) * INV_XAP;
|
||||
bb = B_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
rr += R_VAL(pix) * XAP;
|
||||
gg += G_VAL(pix) * XAP;
|
||||
bb += B_VAL(pix) * XAP;
|
||||
r = ((rr * YAP) + (r * INV_YAP)) >> 16;
|
||||
g = ((gg * YAP) + (g * INV_YAP)) >> 16;
|
||||
b = ((bb * YAP) + (b * INV_YAP)) >> 16;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_YAP;
|
||||
g = G_VAL(pix) * INV_YAP;
|
||||
b = B_VAL(pix) * INV_YAP;
|
||||
ssptr += sow;
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix) * YAP;
|
||||
g += G_VAL(pix) * YAP;
|
||||
b += B_VAL(pix) * YAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XAP > 0)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_XAP;
|
||||
g = G_VAL(pix) * INV_XAP;
|
||||
b = B_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
r += R_VAL(pix) * XAP;
|
||||
g += G_VAL(pix) * XAP;
|
||||
b += B_VAL(pix) * XAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we're scaling down vertically */
|
||||
else if ((xup) && (!yup))
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0;
|
||||
int rr = 0, gg = 0, bb = 0;
|
||||
int count;
|
||||
DATA32 pix;
|
||||
|
||||
if (XAP > 0)
|
||||
{
|
||||
if (YAP > 1)
|
||||
{
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j * sow);
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
}
|
||||
count = j;
|
||||
r = r * INV_XAP / count;
|
||||
g = g * INV_XAP / count;
|
||||
b = b * INV_XAP / count;
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j * sow);
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
rr += R_VAL(pix);
|
||||
gg += G_VAL(pix);
|
||||
bb += B_VAL(pix);
|
||||
}
|
||||
count = j;
|
||||
r = (r + ((rr * XAP) / count)) >> 8;
|
||||
g = (g + ((gg * XAP) / count)) >> 8;
|
||||
b = (b + ((bb * XAP) / count)) >> 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_XAP;
|
||||
g = G_VAL(pix) * INV_XAP;
|
||||
b = B_VAL(pix) * INV_XAP;
|
||||
pix = ssptr[xpoints[x] + 1];
|
||||
r += R_VAL(pix) * XAP;
|
||||
g += G_VAL(pix) * XAP;
|
||||
b += B_VAL(pix) * XAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (YAP > 1)
|
||||
{
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j *sow);
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
}
|
||||
count = j;
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we're scaling down horizontally */
|
||||
else if ((!xup) && (yup))
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0;
|
||||
int rr = 0, gg = 0, bb = 0;
|
||||
int count;
|
||||
DATA32 pix;
|
||||
|
||||
if (YAP > 0)
|
||||
{
|
||||
if (XAP > 1)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
}
|
||||
count = i;
|
||||
r = r * INV_YAP / count;
|
||||
g = g * INV_YAP / count;
|
||||
b = b * INV_YAP / count;
|
||||
ssptr = ypoints[dyy + y] + sow;
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
rr += R_VAL(pix);
|
||||
gg += G_VAL(pix);
|
||||
bb += B_VAL(pix);
|
||||
}
|
||||
count = i;
|
||||
r = (r + ((rr * YAP) / count)) >> 8;
|
||||
g = (g + ((gg * YAP) / count)) >> 8;
|
||||
b = (b + ((bb * YAP) / count)) >> 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
pix = ssptr[xpoints[x]];
|
||||
r = R_VAL(pix) * INV_YAP;
|
||||
g = G_VAL(pix) * INV_YAP;
|
||||
b = B_VAL(pix) * INV_YAP;
|
||||
ssptr += sow;
|
||||
pix = ssptr[xpoints[x]];
|
||||
r += R_VAL(pix) * YAP;
|
||||
g += G_VAL(pix) * YAP;
|
||||
b += B_VAL(pix) * YAP;
|
||||
r >>= 8;
|
||||
g >>= 8;
|
||||
b >>= 8;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XAP > 1)
|
||||
{
|
||||
ssptr = ypoints[dyy + y];
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
}
|
||||
count = i;
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we're scaling down horizontally & vertically */
|
||||
else
|
||||
{
|
||||
/* go through every scanline in the output buffer */
|
||||
for (y = 0; y < dh; y++)
|
||||
{
|
||||
/* calculate the source line we'll scan from */
|
||||
dptr = dest + dx + ((y + dy) * dow);
|
||||
sptr = ypoints[dyy + y];
|
||||
for (x = dxx; x < end; x++)
|
||||
{
|
||||
int r = 0, g = 0, b = 0;
|
||||
int count;
|
||||
DATA32 pix;
|
||||
|
||||
if ((XAP > 1) || (YAP > 1))
|
||||
{
|
||||
for (j = 0; j < YAP; j++)
|
||||
{
|
||||
ssptr = ypoints[dyy + y] + (j * sow);
|
||||
for (i = 0; i < XAP; i++)
|
||||
{
|
||||
pix = ssptr[xpoints[x] + i];
|
||||
r += R_VAL(pix);
|
||||
g += G_VAL(pix);
|
||||
b += B_VAL(pix);
|
||||
}
|
||||
}
|
||||
count = (i * j);
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
pix = RGBA_COMPOSE(r, g, b, 0xff);
|
||||
*dptr++ = pix;
|
||||
}
|
||||
else
|
||||
*dptr++ = sptr[xpoints[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef __SCALE
|
||||
#define __SCALE 1
|
||||
|
||||
DATA32 **
|
||||
CalcYPoints(DATA32 *src, int sw, int sh, int dh, int b1, int b2);
|
||||
int *
|
||||
CalcXPoints(int sw, int dw, int b1, int b2);
|
||||
int *
|
||||
CalcApoints(int s, int d, int b1, int b2);
|
||||
void
|
||||
ScaleSampleRGBA(DATA32 **ypoints, int *xpoints, DATA32 *dest,
|
||||
int dxx, int dyy, int dx, int dy, int dw, int dh, int dow);
|
||||
void
|
||||
ScaleAARGBA(DATA32 **ypoints, int *xpoints, DATA32 *dest,
|
||||
int *xapoints, int *yapoints, char xup, char yup,
|
||||
int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow);
|
||||
void
|
||||
ScaleAARGB(DATA32 **ypoints, int *xpoints, DATA32 *dest,
|
||||
int *xapoints, int *yapoints, char xup, char yup,
|
||||
int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow);
|
||||
#endif
|
Binary file not shown.
After Width: | Height: | Size: 314 KiB |
Binary file not shown.
After Width: | Height: | Size: 296 KiB |
|
@ -0,0 +1,282 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include "common.h"
|
||||
#include "ximage.h"
|
||||
|
||||
/* static private variables */
|
||||
static char x_does_shm = -1;
|
||||
static int list_num = 0;
|
||||
static XImage **list_xim = NULL;
|
||||
static XShmSegmentInfo **list_si = NULL;
|
||||
static Display **list_d = NULL;
|
||||
static char *list_used = NULL;
|
||||
static int list_mem_use = 0;
|
||||
static int list_max_mem = 1024 * 1024 * 1024;
|
||||
static int list_max_count = 1;
|
||||
|
||||
/* temporary X error catcher we use later */
|
||||
static char _x_err = 0;
|
||||
|
||||
/* the fucntion we use for catching the error */
|
||||
static void
|
||||
TmpXError(Display * d, XErrorEvent * ev)
|
||||
{
|
||||
_x_err = 1;
|
||||
}
|
||||
|
||||
void
|
||||
SetMaxXImageCount(Display *d, int num)
|
||||
{
|
||||
list_max_count = num;
|
||||
FlushXImage(d);
|
||||
}
|
||||
|
||||
int
|
||||
GetMaxXImageCount(Display *d)
|
||||
{
|
||||
return list_max_count;
|
||||
}
|
||||
|
||||
void
|
||||
SetMaxXImageTotalSize(Display *d, int num)
|
||||
{
|
||||
list_max_mem = num;
|
||||
FlushXImage(d);
|
||||
}
|
||||
|
||||
int
|
||||
GetMaxXImageTotalSize(Display *d)
|
||||
{
|
||||
return list_max_mem;
|
||||
}
|
||||
|
||||
void
|
||||
FlushXImage(Display *d)
|
||||
{
|
||||
int i;
|
||||
XImage *xim;
|
||||
char did_free = 1;
|
||||
|
||||
while (((list_mem_use > list_max_mem) || (list_num > list_max_count)) &&
|
||||
(did_free))
|
||||
{
|
||||
did_free = 0;
|
||||
for (i = 0; i < list_num; i++)
|
||||
{
|
||||
if (list_used[i] == 0)
|
||||
{
|
||||
int j;
|
||||
|
||||
xim = list_xim[i];
|
||||
list_mem_use -= xim->bytes_per_line * xim->height;
|
||||
if (list_si[i])
|
||||
XShmDetach(d, list_si[i]);
|
||||
XDestroyImage(xim);
|
||||
if (list_si[i])
|
||||
{
|
||||
shmdt(list_si[i]->shmaddr);
|
||||
shmctl(list_si[i]->shmid, IPC_RMID, 0);
|
||||
free(list_si[i]);
|
||||
}
|
||||
list_num--;
|
||||
for (j = i; j < list_num; j++)
|
||||
{
|
||||
list_xim[j] = list_xim[j + 1];
|
||||
list_si[j] = list_si[j + 1];
|
||||
list_used[j] = list_used[j + 1];
|
||||
list_d[j] = list_d[j + 1];
|
||||
}
|
||||
list_xim = realloc(list_xim, sizeof(XImage *) * list_num);
|
||||
list_si = realloc(list_si, sizeof(XShmSegmentInfo *) * list_num);
|
||||
list_used = realloc(list_used, sizeof(char) * list_num);
|
||||
list_d = realloc(list_d, sizeof(Display *) * list_num);
|
||||
did_free = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free (consume == opposite of produce) the XImage (mark as unused) */
|
||||
void
|
||||
ConsumeXImage(Display *d, XImage *xim)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* march through the XImage list */
|
||||
for (i = 0; i < list_num; i++)
|
||||
{
|
||||
/* find a match */
|
||||
if (list_xim[i] == xim)
|
||||
{
|
||||
/* we have a match = mark as unused */
|
||||
list_used[i] = 0;
|
||||
/* flush the XImage list to get rud of stuff we dont want */
|
||||
FlushXImage(d);
|
||||
/* return */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create a new XImage or find it on our list of currently available ones so */
|
||||
/* we dont need to create a new one */
|
||||
XImage *
|
||||
ProduceXImage(Display *d, Visual *v, int depth, int w, int h, char *shared)
|
||||
{
|
||||
XImage *xim;
|
||||
int i;
|
||||
|
||||
/* if we havent check the shm extension before - see if its there */
|
||||
if (x_does_shm < 0)
|
||||
{
|
||||
/* if its there set dose_xhm flag */
|
||||
if (XShmQueryExtension(d))
|
||||
x_does_shm = 1;
|
||||
/* clear the flag - no shm at all */
|
||||
else
|
||||
x_does_shm = 0;
|
||||
}
|
||||
/* find a cached XImage (to avoid server to & fro) that is big enough */
|
||||
/* for our needs and the right depth */
|
||||
*shared = 0;
|
||||
/* go thru the current image list */
|
||||
for (i = 0; i < list_num; i++)
|
||||
{
|
||||
/* if the image has the same depth, width and height - recycle it */
|
||||
/* as long as its not used */
|
||||
if ((list_xim[i]->bits_per_pixel == depth) &&
|
||||
(list_xim[i]->width >= w) &&
|
||||
(list_xim[i]->height >= h) &&
|
||||
/* (list_d[i] == d) &&*/
|
||||
(!list_used[i]))
|
||||
{
|
||||
/* mark it as used */
|
||||
list_used[i] = 1;
|
||||
/* if its shared set shared flag */
|
||||
if (list_si[i])
|
||||
*shared = 1;
|
||||
/* return it */
|
||||
return list_xim[i];
|
||||
}
|
||||
}
|
||||
/* can't find a usable XImage on the cache - create one */
|
||||
/* add the new XImage to the XImage cache */
|
||||
list_num++;
|
||||
list_xim = realloc(list_xim, sizeof(XImage *) * list_num);
|
||||
list_si = realloc(list_si, sizeof(XShmSegmentInfo *) * list_num);
|
||||
list_used = realloc(list_used, sizeof(char) * list_num);
|
||||
list_d = realloc(list_d, sizeof(Display *) * list_num);
|
||||
list_si[list_num - 1] = malloc(sizeof(XShmSegmentInfo));
|
||||
|
||||
/* work on making a shared image */
|
||||
xim = NULL;
|
||||
/* if the server does shm */
|
||||
if (x_does_shm)
|
||||
{
|
||||
/* try create an shm image */
|
||||
xim = XShmCreateImage(d, v, depth, ZPixmap, NULL,
|
||||
list_si[list_num - 1], w, h);
|
||||
/* if it succeeds */
|
||||
if (xim)
|
||||
{
|
||||
/* add to list */
|
||||
list_xim[list_num - 1] = xim;
|
||||
/* get an shm id of this image */
|
||||
list_si[list_num - 1]->shmid =
|
||||
shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
|
||||
IPC_CREAT | 0777);
|
||||
/* if the get succeeds */
|
||||
if (list_si[list_num - 1]->shmid != -1)
|
||||
{
|
||||
/* set the params for the shm segment */
|
||||
list_si[list_num - 1]->readOnly = False;
|
||||
list_si[list_num - 1]->shmaddr = xim->data =
|
||||
shmat(list_si[list_num - 1]->shmid, 0, 0);
|
||||
/* get the shm addr for this data chunk */
|
||||
if (xim->data != (char *)-1)
|
||||
{
|
||||
XErrorHandler ph;
|
||||
|
||||
/* setup a temporary error handler */
|
||||
_x_err = 0;
|
||||
ph = XSetErrorHandler((XErrorHandler) TmpXError);
|
||||
/* ask X to attach to the shared mem segment */
|
||||
XShmAttach(d, list_si[list_num - 1]);
|
||||
/* wait for X to reply and do this */
|
||||
XSync(d, False);
|
||||
/* reset the error handler */
|
||||
XSetErrorHandler((XErrorHandler) ph);
|
||||
/* if we attached without an error we're set */
|
||||
if (!_x_err)
|
||||
{
|
||||
/* mark the image as used */
|
||||
list_used[list_num - 1] = 1;
|
||||
/* incrument our memory count */
|
||||
list_mem_use += xim->bytes_per_line * xim->height;
|
||||
/* set shared flag */
|
||||
*shared = 1;
|
||||
}
|
||||
/* attach by X failed... must be remote client */
|
||||
else
|
||||
{
|
||||
/* flag shm foevere to not work - remote */
|
||||
x_does_shm = 0;
|
||||
/* destroy our previous image */
|
||||
XDestroyImage(xim);
|
||||
/* detach */
|
||||
shmdt(list_si[list_num - 1]->shmaddr);
|
||||
/* remove the shm id */
|
||||
shmctl(list_si[list_num - 1]->shmid, IPC_RMID, 0);
|
||||
/* flag out xim as NULL */
|
||||
xim = NULL;
|
||||
}
|
||||
}
|
||||
/* get failed - out of shm id's or shm segment too big ? */
|
||||
else
|
||||
{
|
||||
/* destroy previous image */
|
||||
XDestroyImage(xim);
|
||||
/* remove the shm id we created */
|
||||
shmctl(list_si[list_num - 1]->shmid, IPC_RMID, 0);
|
||||
/* flag xim as NULL */
|
||||
xim = NULL;
|
||||
}
|
||||
}
|
||||
/* couldnt create SHM image ? */
|
||||
else
|
||||
{
|
||||
/* destroy previous image */
|
||||
XDestroyImage(xim);
|
||||
/* flag xim as NULL */
|
||||
xim = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ok if xim == NULL it all failed - fall back to XImages */
|
||||
if (!xim)
|
||||
{
|
||||
/* get rid of out shm info struct */
|
||||
free(list_si[list_num - 1]);
|
||||
/* flag it as NULL ot indicate a normal XImage */
|
||||
list_si[list_num - 1] = NULL;
|
||||
/* create a normal ximage */
|
||||
xim = XCreateImage(d, v, depth, ZPixmap, 0, NULL, w, h, 32, 0);
|
||||
/* allocate data for it */
|
||||
xim->data = malloc(xim->bytes_per_line * xim->height);
|
||||
/* add xim to our list */
|
||||
list_xim[list_num - 1] = xim;
|
||||
/* incriment our memory count */
|
||||
list_mem_use += xim->bytes_per_line * xim->height;
|
||||
/* mark image as used */
|
||||
list_used[list_num - 1] = 1;
|
||||
/* remember what display that XImage was for */
|
||||
list_d[list_num - 1] = d;
|
||||
}
|
||||
/* flush unused images from the image list */
|
||||
FlushXImage(d);
|
||||
/* return out image */
|
||||
return xim;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __XIMAGE
|
||||
#define __XIMAGE 1
|
||||
void SetMaxXImageCount(Display *d, int num);
|
||||
int GetMaxXImageCount(Display *d);
|
||||
void SetMaxXImageTotalSize(Display *d, int num);
|
||||
int GetMaxXImageTotalSize(Display *d);
|
||||
void FlushXImage(Display *d);
|
||||
void ConsumeXImage(Display *d, XImage *xim);
|
||||
XImage *ProduceXImage(Display *d, Visual *v, int depth, int w, int h, char *shared);
|
||||
#endif
|
Loading…
Reference in New Issue