summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2006-09-15 15:35:16 +0000
committerMatthias Melcher <fltk@matthiasm.com>2006-09-15 15:35:16 +0000
commitc6de2dd3ef9e9a3c17ce210ff1775bd6e183d738 (patch)
treed9a781c366b4b41678267c786c4a411b24957bb0
parentdac4c5630458e1183b5d234aed395971a5642d52 (diff)
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
-rw-r--r--CHANGES1
-rw-r--r--FL/fl_draw.H1
-rw-r--r--src/Fl_Double_Window.cxx44
-rw-r--r--src/Fl_Image.cxx2
-rw-r--r--src/fl_draw_image_win32.cxx68
5 files changed, 94 insertions, 22 deletions
diff --git a/CHANGES b/CHANGES
index 9efe11724..dd16b6fb4 100644
--- a/CHANGES
+++ b/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)
diff --git a/FL/fl_draw.H b/FL/fl_draw.H
index bfd3ef26f..509826ef4 100644
--- a/FL/fl_draw.H
+++ b/FL/fl_draw.H
@@ -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);
diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx
index 54fd2b935..4e5f7bf1b 100644
--- a/src/Fl_Double_Window.cxx
+++ b/src/Fl_Double_Window.cxx
@@ -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
diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx
index 60e56078a..f1247512a 100644
--- a/src/Fl_Image.cxx
+++ b/src/Fl_Image.cxx
@@ -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
diff --git a/src/fl_draw_image_win32.cxx b/src/fl_draw_image_win32.cxx
index a47cbfc10..f55ca9720 100644
--- a/src/fl_draw_image_win32.cxx
+++ b/src/fl_draw_image_win32.cxx
@@ -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) {