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 * MFDRV_CreateBrushIndirect
149 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
156 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
158 switch(logbrush.lbStyle)
166 lb16.lbStyle = logbrush.lbStyle;
167 lb16.lbColor = logbrush.lbColor;
168 lb16.lbHatch = logbrush.lbHatch;
169 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
170 mr = HeapAlloc( GetProcessHeap(), 0, size );
171 mr->rdSize = size / 2;
172 mr->rdFunction = META_CREATEBRUSHINDIRECT;
173 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
178 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
179 BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer;
180 struct gdi_image_bits bits;
183 if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) goto done;
184 if (src_info->bmiHeader.biBitCount != 1)
186 FIXME("Trying to store a colour pattern brush\n");
187 if (bits.free) bits.free( &bits );
191 size = FIELD_OFFSET( METARECORD, rdParm[2] ) +
192 FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage;
194 if (!(mr = HeapAlloc( GetProcessHeap(), 0, size )))
196 if (bits.free) bits.free( &bits );
199 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
200 mr->rdSize = size / 2;
201 mr->rdParm[0] = BS_PATTERN;
202 mr->rdParm[1] = DIB_RGB_COLORS;
203 dst_info = (BITMAPINFO *)(mr->rdParm + 2);
204 dst_info->bmiHeader = src_info->bmiHeader;
205 cref = GetTextColor( dev->hdc );
206 dst_info->bmiColors[0].rgbRed = GetRValue(cref);
207 dst_info->bmiColors[0].rgbGreen = GetGValue(cref);
208 dst_info->bmiColors[0].rgbBlue = GetBValue(cref);
209 dst_info->bmiColors[0].rgbReserved = 0;
210 cref = GetBkColor( dev->hdc );
211 dst_info->bmiColors[1].rgbRed = GetRValue(cref);
212 dst_info->bmiColors[1].rgbGreen = GetGValue(cref);
213 dst_info->bmiColors[1].rgbBlue = GetBValue(cref);
214 dst_info->bmiColors[1].rgbReserved = 0;
216 /* always return a bottom-up DIB */
217 if (dst_info->bmiHeader.biHeight < 0)
219 int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth,
220 dst_info->bmiHeader.biBitCount );
221 char *dst_ptr = (char *)&dst_info->bmiColors[2];
222 dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight;
223 dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes;
224 for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes)
225 memcpy( dst_ptr, (char *)bits.ptr + i * width_bytes, width_bytes );
227 else memcpy( &dst_info->bmiColors[2], bits.ptr, dst_info->bmiHeader.biSizeImage );
228 if (bits.free) bits.free( &bits );
235 DWORD bmSize, biSize;
237 info = GlobalLock( (HGLOBAL)logbrush.lbHatch );
238 if (info->bmiHeader.biCompression)
239 bmSize = info->bmiHeader.biSizeImage;
241 bmSize = get_dib_image_size( info );
242 biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor));
243 size = sizeof(METARECORD) + biSize + bmSize + 2;
244 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
247 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
250 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
251 mr->rdSize = size / 2;
252 *(mr->rdParm) = logbrush.lbStyle;
253 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
254 memcpy(mr->rdParm + 2, info, biSize + bmSize);
255 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
259 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
262 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
263 HeapFree(GetProcessHeap(), 0, mr);
267 return MFDRV_AddHandle( dev, hBrush );
271 /***********************************************************************
274 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
278 index = MFDRV_FindObject(dev, hbrush);
281 index = MFDRV_CreateBrushIndirect( dev, hbrush );
284 GDI_hdc_using_object(hbrush, dev->hdc);
286 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
289 /******************************************************************
290 * MFDRV_CreateFontIndirect
293 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
295 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
296 METARECORD *mr = (METARECORD *)&buffer;
300 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
301 mr->rdFunction = META_CREATEFONTINDIRECT;
302 font16 = (LOGFONT16 *)&mr->rdParm;
304 font16->lfHeight = logfont->lfHeight;
305 font16->lfWidth = logfont->lfWidth;
306 font16->lfEscapement = logfont->lfEscapement;
307 font16->lfOrientation = logfont->lfOrientation;
308 font16->lfWeight = logfont->lfWeight;
309 font16->lfItalic = logfont->lfItalic;
310 font16->lfUnderline = logfont->lfUnderline;
311 font16->lfStrikeOut = logfont->lfStrikeOut;
312 font16->lfCharSet = logfont->lfCharSet;
313 font16->lfOutPrecision = logfont->lfOutPrecision;
314 font16->lfClipPrecision = logfont->lfClipPrecision;
315 font16->lfQuality = logfont->lfQuality;
316 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
317 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
318 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
319 memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
321 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
323 return MFDRV_AddHandle( dev, hFont );
327 /***********************************************************************
330 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
335 index = MFDRV_FindObject(dev, hfont);
338 if (!GetObjectW( hfont, sizeof(font), &font ))
340 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
343 GDI_hdc_using_object(hfont, dev->hdc);
345 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
348 /******************************************************************
349 * MFDRV_CreatePenIndirect
351 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
353 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
354 METARECORD *mr = (METARECORD *)&buffer;
356 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
357 mr->rdFunction = META_CREATEPENINDIRECT;
358 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
359 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
361 return MFDRV_AddHandle( dev, hPen );
365 /***********************************************************************
368 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
373 index = MFDRV_FindObject(dev, hpen);
376 /* must be an extended pen */
377 INT size = GetObjectW( hpen, 0, NULL );
381 if (size == sizeof(LOGPEN))
385 GetObjectW( hpen, sizeof(pen), &pen );
386 logpen.lopnStyle = pen.lopnStyle;
387 logpen.lopnWidth.x = pen.lopnWidth.x;
388 logpen.lopnWidth.y = pen.lopnWidth.y;
389 logpen.lopnColor = pen.lopnColor;
391 else /* must be an extended pen */
393 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
395 GetObjectW( hpen, size, elp );
396 /* FIXME: add support for user style pens */
397 logpen.lopnStyle = elp->elpPenStyle;
398 logpen.lopnWidth.x = elp->elpWidth;
399 logpen.lopnWidth.y = 0;
400 logpen.lopnColor = elp->elpColor;
402 HeapFree( GetProcessHeap(), 0, elp );
405 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
408 GDI_hdc_using_object(hpen, dev->hdc);
410 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
414 /******************************************************************
415 * MFDRV_CreatePalette
417 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
423 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
424 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
425 mr->rdFunction = META_CREATEPALETTE;
426 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
427 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
429 HeapFree(GetProcessHeap(), 0, mr);
433 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
434 mr->rdFunction = META_SELECTPALETTE;
436 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
439 *(mr->rdParm) = index;
440 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
442 HeapFree(GetProcessHeap(), 0, mr);
447 /***********************************************************************
448 * MFDRV_SelectPalette
450 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
452 #define PALVERSION 0x0300
454 PLOGPALETTE logPalette;
455 WORD wNumEntries = 0;
456 BOOL creationSucceed;
459 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
461 if (wNumEntries == 0) return 0;
463 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
464 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
466 if (logPalette == NULL) return 0;
468 logPalette->palVersion = PALVERSION;
469 logPalette->palNumEntries = wNumEntries;
471 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
473 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
475 HeapFree( GetProcessHeap(), 0, logPalette );
483 /***********************************************************************
484 * MFDRV_RealizePalette
486 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
488 char buffer[sizeof(METARECORD) - sizeof(WORD)];
489 METARECORD *mr = (METARECORD *)&buffer;
491 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
492 mr->rdFunction = META_REALIZEPALETTE;
494 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
496 /* The return value is suppose to be the number of entries
497 in the logical palette mapped to the system palette or 0
498 if the function failed. Since it's not trivial here to
499 get that kind of information and since it's of little
500 use in the case of metafiles, we'll always return 1. */