1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
//
// "$Id$"
//
// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2016 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include <config.h>
#include "../../config_lib.h"
#include "Fl_GDI_Graphics_Driver.H"
#include <FL/Fl.H>
#include <FL/x.H>
/* Reference to the current device context
For back-compatibility only. The preferred procedure to get this reference is
Fl_Surface_Device::surface()->driver()->gc().
*/
HDC fl_gc = 0;
void Fl_Graphics_Driver::global_gc()
{
fl_gc = (HDC)gc();
}
/*
* By linking this module, the following static method will instatiate the
* MSWindows GDI Graphics driver as the main display driver.
*/
Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
{
return new Fl_GDI_Graphics_Driver();
}
// 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;
static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
/*
* 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_GDI_Graphics_Driver::can_do_alpha_blending() {
static char been_here = 0;
static char can_do = 0;
// do this test only once
if (been_here) return can_do;
been_here = 1;
// load the library that implements alpha blending
HMODULE hMod = LoadLibrary("MSIMG32.DLL");
// give up if that doesn't exist (Win95?)
if (!hMod) return 0;
// now find the blending function inside that dll
fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend");
// give up if we can't find it (Win95)
if (!fl_alpha_blend) return 0;
// we have the call, but does our display support alpha blending?
// get the desktop's device context
HDC dc = GetDC(0L);
if (!dc) return 0;
// check the device capabilities flags. However GetDeviceCaps
// does not return anything useful, so we have to do it manually:
HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1);
HDC new_gc = CreateCompatibleDC(dc);
int save = SaveDC(new_gc);
SelectObject(new_gc, bm);
/*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101);
BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc);
RestoreDC(new_gc, save);
DeleteDC(new_gc);
DeleteObject(bm);
ReleaseDC(0L, dc);
if (alpha_ok) can_do = 1;
return can_do;
}
HDC fl_makeDC(HBITMAP bitmap) {
HDC new_gc = CreateCompatibleDC((HDC)fl_graphics_driver->gc());
SetTextAlign(new_gc, TA_BASELINE|TA_LEFT);
SetBkMode(new_gc, TRANSPARENT);
#if USE_COLORMAP
if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE);
#endif
SelectObject(new_gc, bitmap);
return new_gc;
}
void Fl_GDI_Graphics_Driver::copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, bitmap);
BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
RestoreDC(new_gc, save);
DeleteDC(new_gc);
}
#if ! defined(FL_DOXYGEN)
void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, bitmap);
BOOL alpha_ok = 0;
// first try to alpha blend
if ( can_do_alpha_blending() ) {
alpha_ok = fl_alpha_blend(gc_, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc);
}
// if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1
if (!alpha_ok) {
BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
}
RestoreDC(new_gc, save);
DeleteDC(new_gc);
}
#endif
void Fl_Translated_GDI_Graphics_Driver::translate_all(int x, int y) {
GetWindowOrgEx((HDC)gc(), origins+depth);
SetWindowOrgEx((HDC)gc(), origins[depth].x - x, origins[depth].y - y, NULL);
if (depth < sizeof(origins)/sizeof(POINT)) depth++;
else Fl::warning("Fl_Copy_Surface: translate stack overflow!");
}
void Fl_Translated_GDI_Graphics_Driver::untranslate_all() {
if (depth > 0) depth--;
SetWindowOrgEx((HDC)gc(), origins[depth].x, origins[depth].y, NULL);
}
void Fl_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
Fl_Region R = XRectangleRegion(X, Y, W, H);
CombineRgn(r, r, R, RGN_OR);
XDestroyRegion(R);
}
void Fl_GDI_Graphics_Driver::transformed_vertex0(int x, int y) {
if (!n || x != p[n-1].x || y != p[n-1].y) {
if (n >= p_size) {
p_size = p ? 2*p_size : 16;
p = (POINT*)realloc((void*)p, p_size*sizeof(*p));
}
p[n].x = x;
p[n].y = y;
n++;
}
}
void Fl_GDI_Graphics_Driver::fixloop() { // remove equal points from closed path
while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--;
}
//
// End of "$Id$".
//
|