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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "mfdrv/metafiledrv.h"
31 #include "gdi_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
36 /******************************************************************
39 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
41 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
44 for(index = 0; index < physDev->handles_size; index++)
45 if(physDev->handles[index] == 0) break;
46 if(index == physDev->handles_size) {
47 physDev->handles_size += HANDLE_LIST_INC;
48 physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
50 physDev->handles_size * sizeof(physDev->handles[0]));
52 physDev->handles[index] = obj;
54 physDev->cur_handles++;
55 if(physDev->cur_handles > physDev->mh->mtNoObjects)
56 physDev->mh->mtNoObjects++;
58 return index ; /* index 0 is not reserved for metafiles */
61 /******************************************************************
64 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
66 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
69 for(index = 0; index < physDev->handles_size; index++)
70 if(physDev->handles[index] == obj) break;
72 if(index == physDev->handles_size) return -1;
78 /******************************************************************
81 BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
84 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
88 index = MFDRV_FindObject(dev, obj);
92 mr.rdSize = sizeof mr / 2;
93 mr.rdFunction = META_DELETEOBJECT;
96 if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
99 physDev->handles[index] = 0;
100 physDev->cur_handles--;
105 /***********************************************************************
108 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
112 mr.rdSize = sizeof mr / 2;
113 mr.rdFunction = META_SELECTOBJECT;
114 mr.rdParm[0] = index;
116 return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
120 /***********************************************************************
123 HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
128 /***********************************************************************
129 * Internal helper for MFDRV_CreateBrushIndirect():
130 * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
132 static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width)
134 int bytes16 = 2 * ((width + 15) / 16);
135 int bytes32 = 4 * ((width + 31) / 32);
142 height = abs(height) - 1;
143 lpSrc = lpRows + height * bytes16;
144 lpDst = lpRows + height * bytes32;
146 /* Note that we work backwards so we can re-pad in place */
149 for (i = bytes32; i > bytes16; i--)
150 lpDst[i - 1] = 0; /* Zero the padding bytes */
152 lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */
159 /***********************************************************************
160 * Internal helper for MFDRV_CreateBrushIndirect():
161 * Reverse order of bitmap rows in going from BMP to DIB.
163 static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width)
165 int bytes = 4 * ((width + 31) / 32);
174 lpDst = lpRows + (height-1) * bytes;
179 for (i = 0; i < bytes; i++)
191 /******************************************************************
192 * MFDRV_CreateBrushIndirect
195 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
200 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
203 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
205 switch(logbrush.lbStyle)
213 lb16.lbStyle = logbrush.lbStyle;
214 lb16.lbColor = logbrush.lbColor;
215 lb16.lbHatch = logbrush.lbHatch;
216 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
217 mr = HeapAlloc( GetProcessHeap(), 0, size );
218 mr->rdSize = size / 2;
219 mr->rdFunction = META_CREATEBRUSHINDIRECT;
220 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
230 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
231 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
232 FIXME("Trying to store a colour pattern brush\n");
236 bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS);
238 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
239 sizeof(RGBQUAD) + bmSize;
241 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
243 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
244 mr->rdSize = size / 2;
245 mr->rdParm[0] = BS_PATTERN;
246 mr->rdParm[1] = DIB_RGB_COLORS;
247 info = (BITMAPINFO *)(mr->rdParm + 2);
249 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
250 info->bmiHeader.biWidth = bm.bmWidth;
251 info->bmiHeader.biHeight = bm.bmHeight;
252 info->bmiHeader.biPlanes = 1;
253 info->bmiHeader.biBitCount = 1;
254 info->bmiHeader.biSizeImage = bmSize;
256 GetBitmapBits((HANDLE)logbrush.lbHatch,
257 bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel),
258 (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
260 /* Change the padding to be DIB compatible if needed */
262 MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
263 bm.bmWidth, bm.bmHeight);
264 /* BMP and DIB have opposite row order conventions */
265 MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
266 bm.bmWidth, bm.bmHeight);
268 cref = GetTextColor(physDev->hdc);
269 info->bmiColors[0].rgbRed = GetRValue(cref);
270 info->bmiColors[0].rgbGreen = GetGValue(cref);
271 info->bmiColors[0].rgbBlue = GetBValue(cref);
272 info->bmiColors[0].rgbReserved = 0;
273 cref = GetBkColor(physDev->hdc);
274 info->bmiColors[1].rgbRed = GetRValue(cref);
275 info->bmiColors[1].rgbGreen = GetGValue(cref);
276 info->bmiColors[1].rgbBlue = GetBValue(cref);
277 info->bmiColors[1].rgbReserved = 0;
284 DWORD bmSize, biSize;
286 info = GlobalLock16((HGLOBAL16)logbrush.lbHatch);
287 if (info->bmiHeader.biCompression)
288 bmSize = info->bmiHeader.biSizeImage;
290 bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
291 info->bmiHeader.biHeight,
292 info->bmiHeader.biBitCount);
293 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush.lbColor));
294 size = sizeof(METARECORD) + biSize + bmSize + 2;
295 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
297 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
298 mr->rdSize = size / 2;
299 *(mr->rdParm) = logbrush.lbStyle;
300 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
301 memcpy(mr->rdParm + 2, info, biSize + bmSize);
305 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
308 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
309 HeapFree(GetProcessHeap(), 0, mr);
313 return MFDRV_AddHandle( dev, hBrush );
317 /***********************************************************************
320 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
322 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
325 index = MFDRV_FindObject(dev, hbrush);
328 index = MFDRV_CreateBrushIndirect( dev, hbrush );
331 GDI_hdc_using_object(hbrush, physDev->hdc);
333 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
336 /******************************************************************
337 * MFDRV_CreateFontIndirect
340 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONT16 *logfont)
342 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
343 METARECORD *mr = (METARECORD *)&buffer;
345 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
346 mr->rdFunction = META_CREATEFONTINDIRECT;
347 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
348 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
350 return MFDRV_AddHandle( dev, hFont );
354 /***********************************************************************
357 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
359 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
363 index = MFDRV_FindObject(dev, hfont);
366 if (!GetObject16( HFONT_16(hfont), sizeof(lf16), &lf16 ))
368 index = MFDRV_CreateFontIndirect(dev, hfont, &lf16);
371 GDI_hdc_using_object(hfont, physDev->hdc);
373 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
376 /******************************************************************
377 * MFDRV_CreatePenIndirect
379 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
381 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
382 METARECORD *mr = (METARECORD *)&buffer;
384 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
385 mr->rdFunction = META_CREATEPENINDIRECT;
386 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
387 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
389 return MFDRV_AddHandle( dev, hPen );
393 /***********************************************************************
396 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
398 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
402 index = MFDRV_FindObject(dev, hpen);
405 if (!GetObject16( HPEN_16(hpen), sizeof(logpen), &logpen ))
407 /* must be an extended pen */
409 INT size = GetObjectW( hpen, 0, NULL );
413 elp = HeapAlloc( GetProcessHeap(), 0, size );
415 GetObjectW( hpen, size, elp );
416 /* FIXME: add support for user style pens */
417 logpen.lopnStyle = elp->elpPenStyle;
418 logpen.lopnWidth.x = elp->elpWidth;
419 logpen.lopnWidth.y = 0;
420 logpen.lopnColor = elp->elpColor;
422 HeapFree( GetProcessHeap(), 0, elp );
425 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
428 GDI_hdc_using_object(hpen, physDev->hdc);
430 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
434 /******************************************************************
435 * MFDRV_CreatePalette
437 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
443 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
444 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
445 mr->rdFunction = META_CREATEPALETTE;
446 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
447 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
449 HeapFree(GetProcessHeap(), 0, mr);
453 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
454 mr->rdFunction = META_SELECTPALETTE;
456 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
459 *(mr->rdParm) = index;
460 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
462 HeapFree(GetProcessHeap(), 0, mr);
467 /***********************************************************************
468 * MFDRV_SelectPalette
470 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
472 #define PALVERSION 0x0300
474 PLOGPALETTE logPalette;
475 WORD wNumEntries = 0;
476 BOOL creationSucceed;
479 GetObjectA(hPalette, sizeof(WORD), (LPSTR) &wNumEntries);
481 if (wNumEntries == 0) return 0;
483 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
484 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
486 if (logPalette == NULL) return 0;
488 logPalette->palVersion = PALVERSION;
489 logPalette->palNumEntries = wNumEntries;
491 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
493 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
495 HeapFree( GetProcessHeap(), 0, logPalette );
503 /***********************************************************************
504 * MFDRV_RealizePalette
506 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
508 char buffer[sizeof(METARECORD) - sizeof(WORD)];
509 METARECORD *mr = (METARECORD *)&buffer;
511 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
512 mr->rdFunction = META_REALIZEPALETTE;
514 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
516 /* The return value is suppose to be the number of entries
517 in the logical palette mapped to the system palette or 0
518 if the function failed. Since it's not trivial here to
519 get that kind of information and since it's of little
520 use in the case of metafiles, we'll always return 1. */