1 /*************************************************************************
2  *
3  *  This code is property of Serenity Systems Intl
4  *  All rights reserverd.
5  *
6  ************************************************************************/
7 
8 #define INCL_WIN
9 #include <svpm.h>
10 
11 #ifndef _OS2CLIPBOARD_HXX_
12 #include "Os2Clipboard.hxx"
13 #endif
14 
15 // same typedefs from win32 sdk
16 typedef unsigned short WORD;
17 typedef unsigned long DWORD;
18 
19 #pragma pack(push, 1)
20 
21 typedef struct {
22   PM_BYTE rgbBlue;
23   PM_BYTE rgbGreen;
24   PM_BYTE rgbRed;
25   PM_BYTE rgbReserved;
26 } RGBQUAD, *LPRGBQUAD;
27 
28 typedef struct
29 {
30     WORD    bfType;
31     DWORD   bfSize;
32     WORD    bfReserved1;
33     WORD    bfReserved2;
34     DWORD   bfOffBits;
35 } W32_BITMAPFILEHEADER, *PW32_BITMAPFILEHEADER;
36 
37 typedef struct
38 {
39     DWORD 	biSize;
40     LONG  	biWidth;
41     LONG  	biHeight;
42     WORD 	biPlanes;
43     WORD 	biBitCount;
44     DWORD 	biCompression;
45     DWORD 	biSizeImage;
46     LONG  	biXPelsPerMeter;
47     LONG  	biYPelsPerMeter;
48     DWORD 	biClrUsed;
49     DWORD 	biClrImportant;
50 } W32_BITMAPINFOHEADER, *PW32_BITMAPINFOHEADER;
51 
52 #pragma pack(pop)
53 
54 // store screen bitcount
55 LONG	lBitCountScreen;
56 
57 /*
58  * Convert an OOo bitmap to an OS/2 bitmap handle
59  *
60  * An OOo bitmap is a BITMAPFILEHEADER structure followed by a Windows DIB
61  *
62  * OS/2 InfoHeader is a superset of Win32 InhoHeader, so we can just copy
63  * the win32 memory over the os2 memory and fix the cbFix field.
64  * colortable and bitmap data share the same format.
65  *
66 */
67 HBITMAP	OOoBmpToOS2Handle( Any &aAnyB)
68 {
69 	// copy bitmap to clipboard
70 	Sequence<sal_Int8> ByteStream;
71 	aAnyB >>= ByteStream;
72 
73 	// get w32 file header data
74 	PW32_BITMAPFILEHEADER pbfh = (PW32_BITMAPFILEHEADER)ByteStream.getArray();
75 	// get w32 info header
76 	PW32_BITMAPINFOHEADER pbih = (PW32_BITMAPINFOHEADER) (pbfh+1);
77 
78 	// create os2 infoheader2 (same fields of w32)
79 	BITMAPINFOHEADER2 bih2;
80 	memset( &bih2, 0, sizeof( bih2));
81 	memcpy( &bih2, pbih, pbih->biSize);
82 	bih2.cbFix = sizeof(bih2);
83 
84 	// Determine size of color table
85 	int iNumColors, numbits=bih2.cPlanes * bih2.cBitCount;
86 	if (numbits != 24)
87 		iNumColors = bih2.cclrUsed ? bih2.cclrUsed : 2<<numbits;
88 	else
89 		iNumColors = bih2.cclrUsed;
90 	int iColorTableSize = iNumColors*sizeof(RGB2);
91 
92 	// allocate bitmap info2 (header2+colortable)
93 	PBITMAPINFO2 pbi2=(PBITMAPINFO2) malloc( sizeof(BITMAPINFOHEADER2)+iColorTableSize);
94 	// setup header fields
95 	memcpy( pbi2, &bih2, sizeof(BITMAPINFOHEADER2));
96 	// copy color palette (follows pbih)
97 	memcpy( &pbi2->argbColor[0], (pbih+1), iColorTableSize);
98 
99 	// get bitmap data
100 	PBYTE pbPelData = (PBYTE)ByteStream.getArray() + pbfh->bfOffBits;
101 	HPS hps = WinGetPS(HWND_DESKTOP);
102 	HBITMAP hbm = GpiCreateBitmap( hps, &bih2, CBM_INIT, pbPelData, pbi2);
103 	debug_printf( "OOoBmpToOS2Handle hbm %x\n", hbm);
104 	WinReleasePS(hps);
105 
106 	// return handle
107 	return hbm;
108 }
109 
110 /*
111  * Convert an OS/2 bitmap handle to OOo bitmap
112  *
113  * First we need to copy the bitmap to a PS, then we can get bitmap data.
114  *
115 */
116 int	OS2HandleToOOoBmp( HBITMAP hbm, Sequence< sal_Int8 >* OOoDIBStream)
117 {
118 	HAB 	hab = WinQueryAnchorBlock(HWND_DESKTOP);
119 	HDC 	hdc;
120 	SIZEL 	sizl;
121 	HPS 	hps;
122 	PM_BYTE*	pbBuffer;
123 	ULONG	cbBuffer;
124 
125 	struct {
126 		BITMAPINFOHEADER2 bmp2;
127 		RGB2 argb2Color[0x100];
128 	} bm;
129 
130 	if (!lBitCountScreen) {
131 		HPS hps = WinGetPS(HWND_DESKTOP);
132 		HDC hdc = GpiQueryDevice(hps);
133 		DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &lBitCountScreen);
134 		WinReleasePS(hps);
135 	}
136 
137 	// STEP 1: get OS/2 bitmap data and header
138 	// get bitmap header
139 	memset(&(bm.bmp2), 0, sizeof(bm.bmp2));
140 	bm.bmp2.cbFix = 16;
141 	GpiQueryBitmapInfoHeader(hbm, &bm.bmp2);
142 
143 	/* Data only actually stored in clipboard quality */
144 	if ( lBitCountScreen < bm.bmp2.cBitCount )
145 		bm.bmp2.cBitCount = lBitCountScreen;
146 
147 	if ( bm.bmp2.cBitCount == 16 )
148 		bm.bmp2.cBitCount = 24;
149 
150 	if ( bm.bmp2.cPlanes != 1 ) {
151 		return 0;
152 	}
153 
154 	if ( (hdc = DevOpenDC(hab, OD_MEMORY, "*", 0L, (PDEVOPENDATA) NULL, (HDC) NULL)) == (HDC) NULL ) {
155 		return 0;
156 	}
157 
158 	sizl.cx = bm.bmp2.cx;
159 	sizl.cy = bm.bmp2.cy;
160 	if ( (hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL ) {
161 		DevCloseDC(hdc);
162 		return 0;
163 	}
164 	// copy bitmap to hps
165 	GpiSetBitmap(hps, hbm);
166 
167 	// buffer lengths
168 	cbBuffer = (((bm.bmp2.cBitCount * bm.bmp2.cx) + 31) / 32) * 4 * bm.bmp2.cy * bm.bmp2.cPlanes;
169 	pbBuffer = (PM_BYTE*) malloc( cbBuffer);
170 	// now get bitmap data
171 	GpiQueryBitmapBits(hps, 0L, (LONG) bm.bmp2.cy, pbBuffer, (BITMAPINFO2*)&bm);
172 	// free OS/2 resources
173 	GpiSetBitmap(hps, (HBITMAP) NULL);
174 	GpiDestroyPS(hps);
175 	DevCloseDC(hdc);
176 
177 	// STEP 2: now convert to Win32 DIB
178 	// Determine size of color table
179 	int iNumColors, numbits=bm.bmp2.cPlanes * bm.bmp2.cBitCount;
180 	if (numbits != 24)
181 		iNumColors = bm.bmp2.cclrUsed ? bm.bmp2.cclrUsed : 2<<numbits;
182 	else
183 		iNumColors = bm.bmp2.cclrUsed;
184 	int iColorTableSize = iNumColors*sizeof(RGBQUAD);
185 
186 	// reallocate data stream object size
187 	OOoDIBStream->realloc( sizeof( W32_BITMAPFILEHEADER )
188 				+ sizeof( W32_BITMAPINFOHEADER) + iColorTableSize + cbBuffer);
189 
190 	// fill w32 file header data
191 	PW32_BITMAPFILEHEADER pbfh = (PW32_BITMAPFILEHEADER) OOoDIBStream->getArray();
192 	memset( pbfh, 0, sizeof( W32_BITMAPFILEHEADER));
193 	pbfh->bfType = 'MB';
194 	pbfh->bfSize = sizeof( W32_BITMAPFILEHEADER )
195 				+ sizeof( W32_BITMAPINFOHEADER) + iColorTableSize + cbBuffer;
196 	pbfh->bfOffBits = sizeof( W32_BITMAPFILEHEADER) + sizeof( W32_BITMAPINFOHEADER) + iColorTableSize;
197 
198 	// fill w32 info header
199 	PW32_BITMAPINFOHEADER pbih = (PW32_BITMAPINFOHEADER) (pbfh+1);
200 	// copy header fields (only win32 ones) and fix size
201 	memcpy( pbih, &bm.bmp2, sizeof(W32_BITMAPINFOHEADER));
202 	pbih->biSize = sizeof(W32_BITMAPINFOHEADER);
203 
204 	// fill color palette (follows pbih)
205 	memcpy( (pbih+1), &bm.argb2Color[0], iColorTableSize);
206 
207 	// fill bitmap data
208 	memcpy( (char*) pbfh + pbfh->bfOffBits, pbBuffer, cbBuffer);
209 
210 	// done
211 	free( pbBuffer);
212 	return 1;
213 }
214 
215 #ifdef TESTBMP
216 
217 #include <io.h>
218 #include <fcntl.h>
219 #include <stdio.h>
220 
221 int main( void)
222 {
223 	HAB hAB = WinQueryAnchorBlock( HWND_DESKTOP );
224 
225 	// query clipboard data to get mimetype
226 	if( WinOpenClipbrd( hAB ) )
227 	{
228 		ULONG handle = WinQueryClipbrdData( hAB, CF_BITMAP);
229 		if (handle) {
230 			Sequence< sal_Int8 > winDIBStream;
231 			// convert to oustring and return it
232 			if (OS2HandleToOOoBmp( handle, &winDIBStream) == 1) {
233 				printf( "Conversion ok.\n");
234 				int fd = open( "test.bmp", O_BINARY | O_CREAT | O_TRUNC | O_RDWR);
235 				printf( "writing to fd %d\n", fd);
236 				write( fd, winDIBStream.getArray(), winDIBStream.getLength());
237 				close( fd);
238 			} else
239 				printf( "failed conversion.\n");
240 
241 		}
242 		WinCloseClipbrd( hAB);
243 	}
244 	return 0;
245 }
246 
247 #endif //TESTBMP
248 
249