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
29 #include "wine/wingdi16.h"
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 BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index )
66 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
69 if (index < physDev->handles_size && physDev->handles[index])
71 physDev->handles[index] = 0;
72 physDev->cur_handles--;
78 /******************************************************************
81 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
83 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
86 for(index = 0; index < physDev->handles_size; index++)
87 if(physDev->handles[index] == obj) break;
89 if(index == physDev->handles_size) return -1;
95 /******************************************************************
98 BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
101 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
105 index = MFDRV_FindObject(dev, obj);
109 mr.rdSize = sizeof mr / 2;
110 mr.rdFunction = META_DELETEOBJECT;
111 mr.rdParm[0] = index;
113 if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
116 physDev->handles[index] = 0;
117 physDev->cur_handles--;
122 /***********************************************************************
125 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
129 mr.rdSize = sizeof mr / 2;
130 mr.rdFunction = META_SELECTOBJECT;
131 mr.rdParm[0] = index;
133 return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
137 /***********************************************************************
140 HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
145 /***********************************************************************
146 * Internal helper for MFDRV_CreateBrushIndirect():
147 * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
149 static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width)
151 int bytes16 = 2 * ((width + 15) / 16);
152 int bytes32 = 4 * ((width + 31) / 32);
159 height = abs(height) - 1;
160 lpSrc = lpRows + height * bytes16;
161 lpDst = lpRows + height * bytes32;
163 /* Note that we work backwards so we can re-pad in place */
166 for (i = bytes32; i > bytes16; i--)
167 lpDst[i - 1] = 0; /* Zero the padding bytes */
169 lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */
176 /***********************************************************************
177 * Internal helper for MFDRV_CreateBrushIndirect():
178 * Reverse order of bitmap rows in going from BMP to DIB.
180 static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width)
182 int bytes = 4 * ((width + 31) / 32);
191 lpDst = lpRows + (height-1) * bytes;
196 for (i = 0; i < bytes; i++)
208 /******************************************************************
209 * MFDRV_CreateBrushIndirect
212 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
219 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
221 switch(logbrush.lbStyle)
229 lb16.lbStyle = logbrush.lbStyle;
230 lb16.lbColor = logbrush.lbColor;
231 lb16.lbHatch = logbrush.lbHatch;
232 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
233 mr = HeapAlloc( GetProcessHeap(), 0, size );
234 mr->rdSize = size / 2;
235 mr->rdFunction = META_CREATEBRUSHINDIRECT;
236 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
246 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
247 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
248 FIXME("Trying to store a colour pattern brush\n");
252 bmSize = get_dib_stride( bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight;
254 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
255 sizeof(RGBQUAD) + bmSize;
257 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
259 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
260 mr->rdSize = size / 2;
261 mr->rdParm[0] = BS_PATTERN;
262 mr->rdParm[1] = DIB_RGB_COLORS;
263 info = (BITMAPINFO *)(mr->rdParm + 2);
265 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
266 info->bmiHeader.biWidth = bm.bmWidth;
267 info->bmiHeader.biHeight = bm.bmHeight;
268 info->bmiHeader.biPlanes = 1;
269 info->bmiHeader.biBitCount = 1;
270 info->bmiHeader.biSizeImage = bmSize;
272 GetBitmapBits((HANDLE)logbrush.lbHatch,
273 bm.bmHeight * get_bitmap_stride(bm.bmWidth, bm.bmBitsPixel),
274 (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
276 /* Change the padding to be DIB compatible if needed */
278 MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
279 bm.bmWidth, bm.bmHeight);
280 /* BMP and DIB have opposite row order conventions */
281 MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
282 bm.bmWidth, bm.bmHeight);
284 cref = GetTextColor( dev->hdc );
285 info->bmiColors[0].rgbRed = GetRValue(cref);
286 info->bmiColors[0].rgbGreen = GetGValue(cref);
287 info->bmiColors[0].rgbBlue = GetBValue(cref);
288 info->bmiColors[0].rgbReserved = 0;
289 cref = GetBkColor( dev->hdc );
290 info->bmiColors[1].rgbRed = GetRValue(cref);
291 info->bmiColors[1].rgbGreen = GetGValue(cref);
292 info->bmiColors[1].rgbBlue = GetBValue(cref);
293 info->bmiColors[1].rgbReserved = 0;
300 DWORD bmSize, biSize;
302 info = GlobalLock( (HGLOBAL)logbrush.lbHatch );
303 if (info->bmiHeader.biCompression)
304 bmSize = info->bmiHeader.biSizeImage;
306 bmSize = get_dib_image_size( info );
307 biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor));
308 size = sizeof(METARECORD) + biSize + bmSize + 2;
309 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
312 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
315 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
316 mr->rdSize = size / 2;
317 *(mr->rdParm) = logbrush.lbStyle;
318 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
319 memcpy(mr->rdParm + 2, info, biSize + bmSize);
320 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
324 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
327 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
328 HeapFree(GetProcessHeap(), 0, mr);
332 return MFDRV_AddHandle( dev, hBrush );
336 /***********************************************************************
339 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
343 index = MFDRV_FindObject(dev, hbrush);
346 index = MFDRV_CreateBrushIndirect( dev, hbrush );
349 GDI_hdc_using_object(hbrush, dev->hdc);
351 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
354 /******************************************************************
355 * MFDRV_CreateFontIndirect
358 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
360 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
361 METARECORD *mr = (METARECORD *)&buffer;
365 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
366 mr->rdFunction = META_CREATEFONTINDIRECT;
367 font16 = (LOGFONT16 *)&mr->rdParm;
369 font16->lfHeight = logfont->lfHeight;
370 font16->lfWidth = logfont->lfWidth;
371 font16->lfEscapement = logfont->lfEscapement;
372 font16->lfOrientation = logfont->lfOrientation;
373 font16->lfWeight = logfont->lfWeight;
374 font16->lfItalic = logfont->lfItalic;
375 font16->lfUnderline = logfont->lfUnderline;
376 font16->lfStrikeOut = logfont->lfStrikeOut;
377 font16->lfCharSet = logfont->lfCharSet;
378 font16->lfOutPrecision = logfont->lfOutPrecision;
379 font16->lfClipPrecision = logfont->lfClipPrecision;
380 font16->lfQuality = logfont->lfQuality;
381 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
382 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
383 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
384 memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
386 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
388 return MFDRV_AddHandle( dev, hFont );
392 /***********************************************************************
395 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
400 index = MFDRV_FindObject(dev, hfont);
403 if (!GetObjectW( hfont, sizeof(font), &font ))
405 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
408 GDI_hdc_using_object(hfont, dev->hdc);
410 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
413 /******************************************************************
414 * MFDRV_CreatePenIndirect
416 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
418 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
419 METARECORD *mr = (METARECORD *)&buffer;
421 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
422 mr->rdFunction = META_CREATEPENINDIRECT;
423 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
424 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
426 return MFDRV_AddHandle( dev, hPen );
430 /***********************************************************************
433 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
438 index = MFDRV_FindObject(dev, hpen);
441 /* must be an extended pen */
442 INT size = GetObjectW( hpen, 0, NULL );
446 if (size == sizeof(LOGPEN))
450 GetObjectW( hpen, sizeof(pen), &pen );
451 logpen.lopnStyle = pen.lopnStyle;
452 logpen.lopnWidth.x = pen.lopnWidth.x;
453 logpen.lopnWidth.y = pen.lopnWidth.y;
454 logpen.lopnColor = pen.lopnColor;
456 else /* must be an extended pen */
458 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
460 GetObjectW( hpen, size, elp );
461 /* FIXME: add support for user style pens */
462 logpen.lopnStyle = elp->elpPenStyle;
463 logpen.lopnWidth.x = elp->elpWidth;
464 logpen.lopnWidth.y = 0;
465 logpen.lopnColor = elp->elpColor;
467 HeapFree( GetProcessHeap(), 0, elp );
470 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
473 GDI_hdc_using_object(hpen, dev->hdc);
475 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
479 /******************************************************************
480 * MFDRV_CreatePalette
482 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
488 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
489 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
490 mr->rdFunction = META_CREATEPALETTE;
491 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
492 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
494 HeapFree(GetProcessHeap(), 0, mr);
498 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
499 mr->rdFunction = META_SELECTPALETTE;
501 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
504 *(mr->rdParm) = index;
505 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
507 HeapFree(GetProcessHeap(), 0, mr);
512 /***********************************************************************
513 * MFDRV_SelectPalette
515 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
517 #define PALVERSION 0x0300
519 PLOGPALETTE logPalette;
520 WORD wNumEntries = 0;
521 BOOL creationSucceed;
524 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
526 if (wNumEntries == 0) return 0;
528 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
529 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
531 if (logPalette == NULL) return 0;
533 logPalette->palVersion = PALVERSION;
534 logPalette->palNumEntries = wNumEntries;
536 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
538 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
540 HeapFree( GetProcessHeap(), 0, logPalette );
548 /***********************************************************************
549 * MFDRV_RealizePalette
551 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
553 char buffer[sizeof(METARECORD) - sizeof(WORD)];
554 METARECORD *mr = (METARECORD *)&buffer;
556 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
557 mr->rdFunction = META_REALIZEPALETTE;
559 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
561 /* The return value is suppose to be the number of entries
562 in the logical palette mapped to the system palette or 0
563 if the function failed. Since it's not trivial here to
564 get that kind of information and since it's of little
565 use in the case of metafiles, we'll always return 1. */