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