4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "mfdrv/metafiledrv.h"
32 #include "gdi_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
37 /******************************************************************
40 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
42 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
45 for(index = 0; index < physDev->handles_size; index++)
46 if(physDev->handles[index] == 0) break;
47 if(index == physDev->handles_size) {
48 physDev->handles_size += HANDLE_LIST_INC;
49 physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
51 physDev->handles_size * sizeof(physDev->handles[0]));
53 physDev->handles[index] = obj;
55 physDev->cur_handles++;
56 if(physDev->cur_handles > physDev->mh->mtNoObjects)
57 physDev->mh->mtNoObjects++;
59 return index ; /* index 0 is not reserved for metafiles */
62 /******************************************************************
65 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
67 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
70 for(index = 0; index < physDev->handles_size; index++)
71 if(physDev->handles[index] == obj) break;
73 if(index == physDev->handles_size) return -1;
79 /******************************************************************
82 BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
85 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
89 index = MFDRV_FindObject(dev, obj);
93 mr.rdSize = sizeof mr / 2;
94 mr.rdFunction = META_DELETEOBJECT;
97 if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
100 physDev->handles[index] = 0;
101 physDev->cur_handles--;
106 /***********************************************************************
109 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
113 mr.rdSize = sizeof mr / 2;
114 mr.rdFunction = META_SELECTOBJECT;
115 mr.rdParm[0] = index;
117 return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
121 /***********************************************************************
124 HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
130 /******************************************************************
131 * MFDRV_CreateBrushIndirect
134 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
139 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
142 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
144 switch(logbrush.lbStyle)
152 lb16.lbStyle = logbrush.lbStyle;
153 lb16.lbColor = logbrush.lbColor;
154 lb16.lbHatch = logbrush.lbHatch;
155 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
156 mr = HeapAlloc( GetProcessHeap(), 0, size );
157 mr->rdSize = size / 2;
158 mr->rdFunction = META_CREATEBRUSHINDIRECT;
159 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
169 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
170 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
171 FIXME("Trying to store a colour pattern brush\n");
175 bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, 1);
177 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
178 sizeof(RGBQUAD) + bmSize;
180 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
182 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
183 mr->rdSize = size / 2;
184 mr->rdParm[0] = BS_PATTERN;
185 mr->rdParm[1] = DIB_RGB_COLORS;
186 info = (BITMAPINFO *)(mr->rdParm + 2);
188 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
189 info->bmiHeader.biWidth = bm.bmWidth;
190 info->bmiHeader.biHeight = bm.bmHeight;
191 info->bmiHeader.biPlanes = 1;
192 info->bmiHeader.biBitCount = 1;
193 bits = ((BYTE *)info) + sizeof(BITMAPINFO) + sizeof(RGBQUAD);
195 GetDIBits(physDev->hdc, (HANDLE)logbrush.lbHatch, 0, bm.bmHeight,
196 bits, info, DIB_RGB_COLORS);
197 *(DWORD *)info->bmiColors = 0;
198 *(DWORD *)(info->bmiColors + 1) = 0xffffff;
205 DWORD bmSize, biSize;
207 info = GlobalLock16((HGLOBAL16)logbrush.lbHatch);
208 if (info->bmiHeader.biCompression)
209 bmSize = info->bmiHeader.biSizeImage;
211 bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
212 info->bmiHeader.biHeight,
213 info->bmiHeader.biBitCount);
214 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush.lbColor));
215 size = sizeof(METARECORD) + biSize + bmSize + 2;
216 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
218 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
219 mr->rdSize = size / 2;
220 *(mr->rdParm) = logbrush.lbStyle;
221 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
222 memcpy(mr->rdParm + 2, info, biSize + bmSize);
226 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
229 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
230 HeapFree(GetProcessHeap(), 0, mr);
234 return MFDRV_AddHandle( dev, hBrush );
238 /***********************************************************************
241 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
243 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
246 index = MFDRV_FindObject(dev, hbrush);
249 index = MFDRV_CreateBrushIndirect( dev, hbrush );
252 GDI_hdc_using_object(hbrush, physDev->hdc);
254 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
257 /******************************************************************
258 * MFDRV_CreateFontIndirect
261 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONT16 *logfont)
263 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
264 METARECORD *mr = (METARECORD *)&buffer;
266 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
267 mr->rdFunction = META_CREATEFONTINDIRECT;
268 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
269 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
271 return MFDRV_AddHandle( dev, hFont );
275 /***********************************************************************
278 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
280 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
284 index = MFDRV_FindObject(dev, hfont);
287 if (!GetObject16( HFONT_16(hfont), sizeof(lf16), &lf16 ))
289 index = MFDRV_CreateFontIndirect(dev, hfont, &lf16);
292 GDI_hdc_using_object(hfont, physDev->hdc);
294 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
297 /******************************************************************
298 * MFDRV_CreatePenIndirect
300 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
302 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
303 METARECORD *mr = (METARECORD *)&buffer;
305 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
306 mr->rdFunction = META_CREATEPENINDIRECT;
307 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
308 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
310 return MFDRV_AddHandle( dev, hPen );
314 /***********************************************************************
317 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
319 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
323 index = MFDRV_FindObject(dev, hpen);
326 if (!GetObject16( HPEN_16(hpen), sizeof(logpen), &logpen ))
328 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
331 GDI_hdc_using_object(hpen, physDev->hdc);
333 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
337 /******************************************************************
338 * MFDRV_CreatePalette
340 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
346 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
347 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
348 mr->rdFunction = META_CREATEPALETTE;
349 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
350 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
352 HeapFree(GetProcessHeap(), 0, mr);
356 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
357 mr->rdFunction = META_SELECTPALETTE;
359 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
362 *(mr->rdParm) = index;
363 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
365 HeapFree(GetProcessHeap(), 0, mr);
370 /***********************************************************************
371 * MFDRV_SelectPalette
373 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
375 #define PALVERSION 0x0300
377 PLOGPALETTE logPalette;
378 WORD wNumEntries = 0;
379 BOOL creationSucceed;
382 GetObjectA(hPalette, sizeof(WORD), (LPSTR) &wNumEntries);
384 if (wNumEntries == 0) return 0;
386 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
387 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
389 if (logPalette == NULL) return 0;
391 logPalette->palVersion = PALVERSION;
392 logPalette->palNumEntries = wNumEntries;
394 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
396 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
398 HeapFree( GetProcessHeap(), 0, logPalette );
406 /***********************************************************************
407 * MFDRV_RealizePalette
409 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
411 char buffer[sizeof(METARECORD) - sizeof(WORD)];
412 METARECORD *mr = (METARECORD *)&buffer;
414 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
415 mr->rdFunction = META_REALIZEPALETTE;
417 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
419 /* The return value is suppose to be the number of entries
420 in the logical palette mapped to the system palette or 0
421 if the function failed. Since it's not trivial here to
422 get that kind of information and since it's of little
423 use in the case of metafiles, we'll always return 1. */