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