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 )
129 /***********************************************************************
130 * Internal helper for MFDRV_CreateBrushIndirect():
131 * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
133 static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width)
135 int bytes16 = 2 * ((width + 15) / 16);
136 int bytes32 = 4 * ((width + 31) / 32);
143 height = abs(height) - 1;
144 lpSrc = lpRows + height * bytes16;
145 lpDst = lpRows + height * bytes32;
147 /* Note that we work backwards so we can re-pad in place */
150 for (i = bytes32; i > bytes16; i--)
151 lpDst[i - 1] = 0; /* Zero the padding bytes */
153 lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */
160 /***********************************************************************
161 * Internal helper for MFDRV_CreateBrushIndirect():
162 * Reverse order of bitmap rows in going from BMP to DIB.
164 static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width)
166 int bytes = 4 * ((width + 31) / 32);
175 lpDst = lpRows + (height-1) * bytes;
180 for (i = 0; i < bytes; i++)
192 /******************************************************************
193 * MFDRV_CreateBrushIndirect
196 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
201 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
204 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
206 switch(logbrush.lbStyle)
214 lb16.lbStyle = logbrush.lbStyle;
215 lb16.lbColor = logbrush.lbColor;
216 lb16.lbHatch = logbrush.lbHatch;
217 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
218 mr = HeapAlloc( GetProcessHeap(), 0, size );
219 mr->rdSize = size / 2;
220 mr->rdFunction = META_CREATEBRUSHINDIRECT;
221 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
231 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
232 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
233 FIXME("Trying to store a colour pattern brush\n");
237 bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS);
239 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
240 sizeof(RGBQUAD) + bmSize;
242 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
244 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
245 mr->rdSize = size / 2;
246 mr->rdParm[0] = BS_PATTERN;
247 mr->rdParm[1] = DIB_RGB_COLORS;
248 info = (BITMAPINFO *)(mr->rdParm + 2);
250 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
251 info->bmiHeader.biWidth = bm.bmWidth;
252 info->bmiHeader.biHeight = bm.bmHeight;
253 info->bmiHeader.biPlanes = 1;
254 info->bmiHeader.biBitCount = 1;
255 info->bmiHeader.biSizeImage = bmSize;
257 GetBitmapBits((HANDLE)logbrush.lbHatch,
258 bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel),
259 (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
261 /* Change the padding to be DIB compatible if needed */
263 MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
264 bm.bmWidth, bm.bmHeight);
265 /* BMP and DIB have opposite row order conventions */
266 MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
267 bm.bmWidth, bm.bmHeight);
269 cref = GetTextColor(physDev->hdc);
270 info->bmiColors[0].rgbRed = GetRValue(cref);
271 info->bmiColors[0].rgbGreen = GetGValue(cref);
272 info->bmiColors[0].rgbBlue = GetBValue(cref);
273 info->bmiColors[0].rgbReserved = 0;
274 cref = GetBkColor(physDev->hdc);
275 info->bmiColors[1].rgbRed = GetRValue(cref);
276 info->bmiColors[1].rgbGreen = GetGValue(cref);
277 info->bmiColors[1].rgbBlue = GetBValue(cref);
278 info->bmiColors[1].rgbReserved = 0;
285 DWORD bmSize, biSize;
287 info = GlobalLock16((HGLOBAL16)logbrush.lbHatch);
288 if (info->bmiHeader.biCompression)
289 bmSize = info->bmiHeader.biSizeImage;
291 bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
292 info->bmiHeader.biHeight,
293 info->bmiHeader.biBitCount);
294 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush.lbColor));
295 size = sizeof(METARECORD) + biSize + bmSize + 2;
296 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
298 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
299 mr->rdSize = size / 2;
300 *(mr->rdParm) = logbrush.lbStyle;
301 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
302 memcpy(mr->rdParm + 2, info, biSize + bmSize);
306 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
309 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
310 HeapFree(GetProcessHeap(), 0, mr);
314 return MFDRV_AddHandle( dev, hBrush );
318 /***********************************************************************
321 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
323 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
326 index = MFDRV_FindObject(dev, hbrush);
329 index = MFDRV_CreateBrushIndirect( dev, hbrush );
332 GDI_hdc_using_object(hbrush, physDev->hdc);
334 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
337 /******************************************************************
338 * MFDRV_CreateFontIndirect
341 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONT16 *logfont)
343 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
344 METARECORD *mr = (METARECORD *)&buffer;
346 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
347 mr->rdFunction = META_CREATEFONTINDIRECT;
348 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
349 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
351 return MFDRV_AddHandle( dev, hFont );
355 /***********************************************************************
358 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
360 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
364 index = MFDRV_FindObject(dev, hfont);
367 if (!GetObject16( HFONT_16(hfont), sizeof(lf16), &lf16 ))
369 index = MFDRV_CreateFontIndirect(dev, hfont, &lf16);
372 GDI_hdc_using_object(hfont, physDev->hdc);
374 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
377 /******************************************************************
378 * MFDRV_CreatePenIndirect
380 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
382 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
383 METARECORD *mr = (METARECORD *)&buffer;
385 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
386 mr->rdFunction = META_CREATEPENINDIRECT;
387 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
388 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
390 return MFDRV_AddHandle( dev, hPen );
394 /***********************************************************************
397 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
399 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
403 index = MFDRV_FindObject(dev, hpen);
406 if (!GetObject16( HPEN_16(hpen), sizeof(logpen), &logpen ))
408 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
411 GDI_hdc_using_object(hpen, physDev->hdc);
413 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
417 /******************************************************************
418 * MFDRV_CreatePalette
420 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
426 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
427 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
428 mr->rdFunction = META_CREATEPALETTE;
429 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
430 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
432 HeapFree(GetProcessHeap(), 0, mr);
436 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
437 mr->rdFunction = META_SELECTPALETTE;
439 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
442 *(mr->rdParm) = index;
443 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
445 HeapFree(GetProcessHeap(), 0, mr);
450 /***********************************************************************
451 * MFDRV_SelectPalette
453 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
455 #define PALVERSION 0x0300
457 PLOGPALETTE logPalette;
458 WORD wNumEntries = 0;
459 BOOL creationSucceed;
462 GetObjectA(hPalette, sizeof(WORD), (LPSTR) &wNumEntries);
464 if (wNumEntries == 0) return 0;
466 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
467 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
469 if (logPalette == NULL) return 0;
471 logPalette->palVersion = PALVERSION;
472 logPalette->palNumEntries = wNumEntries;
474 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
476 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
478 HeapFree( GetProcessHeap(), 0, logPalette );
486 /***********************************************************************
487 * MFDRV_RealizePalette
489 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
491 char buffer[sizeof(METARECORD) - sizeof(WORD)];
492 METARECORD *mr = (METARECORD *)&buffer;
494 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
495 mr->rdFunction = META_REALIZEPALETTE;
497 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
499 /* The return value is suppose to be the number of entries
500 in the logical palette mapped to the system palette or 0
501 if the function failed. Since it's not trivial here to
502 get that kind of information and since it's of little
503 use in the case of metafiles, we'll always return 1. */