Implemented alpha blending for WIN32. I believe that I did it in a way that is compatible even with Windows 95, but please let me know if you have any concerns. Cygwin not tested, but hopefully OK.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@5430 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
dac4c56304
commit
c6de2dd3ef
1
CHANGES
1
CHANGES
@ -1,5 +1,6 @@
|
||||
CHANGES IN FLTK 1.1.8
|
||||
|
||||
- Implemented alpha blending for WIN32
|
||||
- Updated documentation (STR #1420, STR #1421)
|
||||
- Fixed font caching issue (STR #1415)
|
||||
- Fixed crash in fl_file_chooser (STR #1410)
|
||||
|
||||
@ -178,6 +178,7 @@ typedef void (*Fl_Draw_Image_Cb)(void*,int,int,int,uchar*);
|
||||
FL_EXPORT void fl_draw_image(Fl_Draw_Image_Cb, void*, int,int,int,int, int delta=3);
|
||||
FL_EXPORT void fl_draw_image_mono(Fl_Draw_Image_Cb, void*, int,int,int,int, int delta=1);
|
||||
FL_EXPORT void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b);
|
||||
FL_EXPORT char fl_can_do_alpha_blending();
|
||||
|
||||
FL_EXPORT uchar *fl_read_image(uchar *p, int x,int y, int w, int h, int alpha=0);
|
||||
|
||||
|
||||
@ -76,6 +76,28 @@ void Fl_Double_Window::show() {
|
||||
// Code used to switch output to an off-screen window. See macros in
|
||||
// win32.H which save the old state in local variables.
|
||||
|
||||
typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION;
|
||||
typedef BOOL (WINAPI* fl_alpha_blend_func)
|
||||
(HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION);
|
||||
static fl_alpha_blend_func fl_alpha_blend = NULL;
|
||||
|
||||
/*
|
||||
* This function checks if the version of MSWindows that we
|
||||
* curently run on supports alpha blending for bitmap transfers
|
||||
* and finds the required function if so.
|
||||
*/
|
||||
char fl_can_do_alpha_blending() {
|
||||
static char been_here = 0;
|
||||
static char can_do = 0;
|
||||
if (been_here) return can_do;
|
||||
HMODULE hMod = LoadLibrary("MSIMG32.DLL");
|
||||
if (!hMod) return 0;
|
||||
fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend");
|
||||
if (!fl_alpha_blend) return 0;
|
||||
can_do = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
HDC fl_makeDC(HBITMAP bitmap) {
|
||||
HDC new_gc = CreateCompatibleDC(fl_gc);
|
||||
SetTextAlign(new_gc, TA_BASELINE|TA_LEFT);
|
||||
@ -88,10 +110,15 @@ HDC fl_makeDC(HBITMAP bitmap) {
|
||||
}
|
||||
|
||||
void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
|
||||
static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
|
||||
|
||||
HDC new_gc = CreateCompatibleDC(fl_gc);
|
||||
int save = SaveDC(new_gc);
|
||||
SelectObject(new_gc, bitmap);
|
||||
BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
|
||||
if (fl_can_do_alpha_blending())
|
||||
fl_alpha_blend(fl_gc, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc);
|
||||
else
|
||||
BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
|
||||
RestoreDC(new_gc, save);
|
||||
DeleteDC(new_gc);
|
||||
}
|
||||
@ -100,6 +127,10 @@ extern void fl_restore_clip();
|
||||
|
||||
#elif defined(__APPLE_QD__)
|
||||
|
||||
char fl_can_do_alpha_blending() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GWorldPtr fl_create_offscreen(int w, int h) {
|
||||
GWorldPtr gw;
|
||||
Rect bounds;
|
||||
@ -173,6 +204,10 @@ extern void fl_restore_clip();
|
||||
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
|
||||
char fl_can_do_alpha_blending() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Fl_Offscreen fl_create_offscreen(int w, int h) {
|
||||
void *data = calloc(w*h,4);
|
||||
CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
|
||||
@ -254,6 +289,13 @@ void fl_end_offscreen() {
|
||||
|
||||
extern void fl_restore_clip();
|
||||
|
||||
#else // X11
|
||||
|
||||
// maybe someone feels inclined to implement alpha blending on X11?
|
||||
char fl_can_do_alpha_blending() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Fl_Overlay_Window relies on flush(1) copying the back buffer to the
|
||||
|
||||
@ -352,7 +352,7 @@ void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
fl_begin_offscreen((Fl_Offscreen)id);
|
||||
fl_draw_image(array, 0, 0, w(), h(), d(), ld());
|
||||
fl_end_offscreen();
|
||||
if (d() == 2 || d() == 4) {
|
||||
if (d() == 2 || d() == 4 && !fl_can_do_alpha_blending()) {
|
||||
mask = fl_create_alphamask(w(), h(), d(), ld(), array);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -112,13 +112,17 @@ static void monodither(uchar* to, const uchar* from, int w, int delta) {
|
||||
#endif // USE_COLORMAP
|
||||
|
||||
static void innards(const uchar *buf, int X, int Y, int W, int H,
|
||||
int delta, int linedelta, int mono,
|
||||
int delta, int linedelta, int depth,
|
||||
Fl_Draw_Image_Cb cb, void* userdata)
|
||||
{
|
||||
#if USE_COLORMAP
|
||||
char indexed = (fl_palette != 0);
|
||||
#endif
|
||||
|
||||
if (depth==0) depth = 3;
|
||||
if (indexed || !fl_can_do_alpha_blending())
|
||||
depth = (depth-1)|1;
|
||||
|
||||
if (!linedelta) linedelta = W*delta;
|
||||
|
||||
int x, y, w, h;
|
||||
@ -144,7 +148,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (mono) {
|
||||
if (depth<3) {
|
||||
for (int i=0; i<256; i++) {
|
||||
bmi.bmiColors[i].rgbBlue = (uchar)i;
|
||||
bmi.bmiColors[i].rgbGreen = (uchar)i;
|
||||
@ -154,11 +158,11 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
|
||||
}
|
||||
bmi.bmiHeader.biWidth = w;
|
||||
#if USE_COLORMAP
|
||||
bmi.bmiHeader.biBitCount = mono|indexed ? 8 : 24;
|
||||
int pixelsize = mono|indexed ? 1 : 3;
|
||||
bmi.bmiHeader.biBitCount = indexed ? 8 : depth*8;
|
||||
int pixelsize = indexed ? 1 : depth;
|
||||
#else
|
||||
bmi.bmiHeader.biBitCount = mono ? 8 : 24;
|
||||
int pixelsize = mono ? 1 : 3;
|
||||
bmi.bmiHeader.biBitCount = depth*8;
|
||||
int pixelsize = depth;
|
||||
#endif
|
||||
int linesize = (pixelsize*w+3)&~3;
|
||||
|
||||
@ -200,22 +204,44 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
|
||||
uchar *to = (uchar*)buffer+(blocking-k-1)*linesize;
|
||||
#if USE_COLORMAP
|
||||
if (indexed) {
|
||||
if (mono)
|
||||
if (depth<3)
|
||||
monodither(to, from, w, delta);
|
||||
else
|
||||
dither(to, from, w, delta);
|
||||
to += w;
|
||||
} else
|
||||
#endif
|
||||
if (mono) {
|
||||
for (int i=w; i--; from += delta) *to++ = *from;
|
||||
} else {
|
||||
for (int i=w; i--; from += delta, to += 3) {
|
||||
uchar r = from[0];
|
||||
to[0] = from[2];
|
||||
to[1] = from[1];
|
||||
to[2] = r;
|
||||
}
|
||||
{
|
||||
int i;
|
||||
switch (depth) {
|
||||
case 1:
|
||||
for (i=w; i--; from += delta) *to++ = *from;
|
||||
break;
|
||||
case 2:
|
||||
for (i=w; i--; from += delta) {
|
||||
*to++ = *from;
|
||||
*to++ = *from;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (i=w; i--; from += delta, to += 3) {
|
||||
uchar r = from[0];
|
||||
to[0] = from[2];
|
||||
to[1] = from[1];
|
||||
to[2] = r;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (i=w; i--; from += delta, to += 4) {
|
||||
uchar a = from[3];
|
||||
uchar r = from[0];
|
||||
to[0] = (from[2]*a)>>8;
|
||||
to[1] = (from[1]*a)>>8;
|
||||
to[2] = (r*a)>>8;
|
||||
to[3] = from[3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetDIBitsToDevice(fl_gc, x, y+j-k, w, k, 0, 0, 0, k,
|
||||
@ -230,19 +256,21 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
|
||||
}
|
||||
}
|
||||
|
||||
static int fl_abs(int v) { return v<0 ? -v : v; }
|
||||
|
||||
void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
|
||||
innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0);
|
||||
innards(buf,x,y,w,h,d,l,fl_abs(d),0,0);
|
||||
}
|
||||
void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
|
||||
int x, int y, int w, int h,int d) {
|
||||
innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
|
||||
innards(0,x,y,w,h,d,0,fl_abs(d),cb,data);
|
||||
}
|
||||
void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
|
||||
innards(buf,x,y,w,h,d,l,1,0,0);
|
||||
innards(buf,x,y,w,h,d,l,fl_abs(d),0,0);
|
||||
}
|
||||
void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
|
||||
int x, int y, int w, int h,int d) {
|
||||
innards(0,x,y,w,h,d,0,1,cb,data);
|
||||
innards(0,x,y,w,h,d,0,fl_abs(d),cb,data);
|
||||
}
|
||||
|
||||
void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user