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 dst_info
->bmiHeader
.biClrUsed
= 0;
206 cref
= GetTextColor( dev
->hdc
);
207 dst_info
->bmiColors
[0].rgbRed
= GetRValue(cref
);
208 dst_info
->bmiColors
[0].rgbGreen
= GetGValue(cref
);
209 dst_info
->bmiColors
[0].rgbBlue
= GetBValue(cref
);
210 dst_info
->bmiColors
[0].rgbReserved
= 0;
211 cref
= GetBkColor( dev
->hdc
);
212 dst_info
->bmiColors
[1].rgbRed
= GetRValue(cref
);
213 dst_info
->bmiColors
[1].rgbGreen
= GetGValue(cref
);
214 dst_info
->bmiColors
[1].rgbBlue
= GetBValue(cref
);
215 dst_info
->bmiColors
[1].rgbReserved
= 0;
217 /* always return a bottom-up DIB */
218 if (dst_info
->bmiHeader
.biHeight
< 0)
220 int i
, width_bytes
= get_dib_stride( dst_info
->bmiHeader
.biWidth
,
221 dst_info
->bmiHeader
.biBitCount
);
222 char *dst_ptr
= (char *)&dst_info
->bmiColors
[2];
223 dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
224 dst_ptr
+= (dst_info
->bmiHeader
.biHeight
- 1) * width_bytes
;
225 for (i
= 0; i
< dst_info
->bmiHeader
.biHeight
; i
++, dst_ptr
-= width_bytes
)
226 memcpy( dst_ptr
, (char *)bits
.ptr
+ i
* width_bytes
, width_bytes
);
228 else memcpy( &dst_info
->bmiColors
[2], bits
.ptr
, dst_info
->bmiHeader
.biSizeImage
);
229 if (bits
.free
) bits
.free( &bits
);
236 DWORD bmSize
, biSize
;
238 info
= GlobalLock( (HGLOBAL
)logbrush
.lbHatch
);
239 if (info
->bmiHeader
.biCompression
)
240 bmSize
= info
->bmiHeader
.biSizeImage
;
242 bmSize
= get_dib_image_size( info
);
243 biSize
= bitmap_info_size(info
, LOWORD(logbrush
.lbColor
));
244 size
= sizeof(METARECORD
) + biSize
+ bmSize
+ 2;
245 mr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
248 GlobalUnlock( (HGLOBAL
)logbrush
.lbHatch
);
251 mr
->rdFunction
= META_DIBCREATEPATTERNBRUSH
;
252 mr
->rdSize
= size
/ 2;
253 *(mr
->rdParm
) = logbrush
.lbStyle
;
254 *(mr
->rdParm
+ 1) = LOWORD(logbrush
.lbColor
);
255 memcpy(mr
->rdParm
+ 2, info
, biSize
+ bmSize
);
256 GlobalUnlock( (HGLOBAL
)logbrush
.lbHatch
);
260 FIXME("Unkonwn brush style %x\n", logbrush
.lbStyle
);
263 r
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2);
264 HeapFree(GetProcessHeap(), 0, mr
);
268 return MFDRV_AddHandle( dev
, hBrush
);
272 /***********************************************************************
275 HBRUSH
MFDRV_SelectBrush( PHYSDEV dev
, HBRUSH hbrush
)
279 index
= MFDRV_FindObject(dev
, hbrush
);
282 index
= MFDRV_CreateBrushIndirect( dev
, hbrush
);
285 GDI_hdc_using_object(hbrush
, dev
->hdc
);
287 return MFDRV_SelectObject( dev
, index
) ? hbrush
: HGDI_ERROR
;
290 /******************************************************************
291 * MFDRV_CreateFontIndirect
294 static UINT16
MFDRV_CreateFontIndirect(PHYSDEV dev
, HFONT hFont
, LOGFONTW
*logfont
)
296 char buffer
[sizeof(METARECORD
) - 2 + sizeof(LOGFONT16
)];
297 METARECORD
*mr
= (METARECORD
*)&buffer
;
301 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(LOGFONT16
) - 2) / 2;
302 mr
->rdFunction
= META_CREATEFONTINDIRECT
;
303 font16
= (LOGFONT16
*)&mr
->rdParm
;
305 font16
->lfHeight
= logfont
->lfHeight
;
306 font16
->lfWidth
= logfont
->lfWidth
;
307 font16
->lfEscapement
= logfont
->lfEscapement
;
308 font16
->lfOrientation
= logfont
->lfOrientation
;
309 font16
->lfWeight
= logfont
->lfWeight
;
310 font16
->lfItalic
= logfont
->lfItalic
;
311 font16
->lfUnderline
= logfont
->lfUnderline
;
312 font16
->lfStrikeOut
= logfont
->lfStrikeOut
;
313 font16
->lfCharSet
= logfont
->lfCharSet
;
314 font16
->lfOutPrecision
= logfont
->lfOutPrecision
;
315 font16
->lfClipPrecision
= logfont
->lfClipPrecision
;
316 font16
->lfQuality
= logfont
->lfQuality
;
317 font16
->lfPitchAndFamily
= logfont
->lfPitchAndFamily
;
318 written
= WideCharToMultiByte( CP_ACP
, 0, logfont
->lfFaceName
, -1, font16
->lfFaceName
, LF_FACESIZE
- 1, NULL
, NULL
);
319 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
320 memset(font16
->lfFaceName
+ written
, 0, LF_FACESIZE
- written
);
322 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
324 return MFDRV_AddHandle( dev
, hFont
);
328 /***********************************************************************
331 HFONT
MFDRV_SelectFont( PHYSDEV dev
, HFONT hfont
, HANDLE gdiFont
)
336 index
= MFDRV_FindObject(dev
, hfont
);
339 if (!GetObjectW( hfont
, sizeof(font
), &font
))
341 index
= MFDRV_CreateFontIndirect(dev
, hfont
, &font
);
344 GDI_hdc_using_object(hfont
, dev
->hdc
);
346 return MFDRV_SelectObject( dev
, index
) ? hfont
: HGDI_ERROR
;
349 /******************************************************************
350 * MFDRV_CreatePenIndirect
352 static UINT16
MFDRV_CreatePenIndirect(PHYSDEV dev
, HPEN hPen
, LOGPEN16
*logpen
)
354 char buffer
[sizeof(METARECORD
) - 2 + sizeof(*logpen
)];
355 METARECORD
*mr
= (METARECORD
*)&buffer
;
357 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(*logpen
) - 2) / 2;
358 mr
->rdFunction
= META_CREATEPENINDIRECT
;
359 memcpy(&(mr
->rdParm
), logpen
, sizeof(*logpen
));
360 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
362 return MFDRV_AddHandle( dev
, hPen
);
366 /***********************************************************************
369 HPEN
MFDRV_SelectPen( PHYSDEV dev
, HPEN hpen
)
374 index
= MFDRV_FindObject(dev
, hpen
);
377 /* must be an extended pen */
378 INT size
= GetObjectW( hpen
, 0, NULL
);
382 if (size
== sizeof(LOGPEN
))
386 GetObjectW( hpen
, sizeof(pen
), &pen
);
387 logpen
.lopnStyle
= pen
.lopnStyle
;
388 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
389 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
390 logpen
.lopnColor
= pen
.lopnColor
;
392 else /* must be an extended pen */
394 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
396 GetObjectW( hpen
, size
, elp
);
397 /* FIXME: add support for user style pens */
398 logpen
.lopnStyle
= elp
->elpPenStyle
;
399 logpen
.lopnWidth
.x
= elp
->elpWidth
;
400 logpen
.lopnWidth
.y
= 0;
401 logpen
.lopnColor
= elp
->elpColor
;
403 HeapFree( GetProcessHeap(), 0, elp
);
406 index
= MFDRV_CreatePenIndirect( dev
, hpen
, &logpen
);
409 GDI_hdc_using_object(hpen
, dev
->hdc
);
411 return MFDRV_SelectObject( dev
, index
) ? hpen
: HGDI_ERROR
;
415 /******************************************************************
416 * MFDRV_CreatePalette
418 static BOOL
MFDRV_CreatePalette(PHYSDEV dev
, HPALETTE hPalette
, LOGPALETTE
* logPalette
, int sizeofPalette
)
424 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
425 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
426 mr
->rdFunction
= META_CREATEPALETTE
;
427 memcpy(&(mr
->rdParm
), logPalette
, sizeofPalette
);
428 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
))))
430 HeapFree(GetProcessHeap(), 0, mr
);
434 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
435 mr
->rdFunction
= META_SELECTPALETTE
;
437 if ((index
= MFDRV_AddHandle( dev
, hPalette
)) == -1) ret
= FALSE
;
440 *(mr
->rdParm
) = index
;
441 ret
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
));
443 HeapFree(GetProcessHeap(), 0, mr
);
448 /***********************************************************************
449 * MFDRV_SelectPalette
451 HPALETTE
MFDRV_SelectPalette( PHYSDEV dev
, HPALETTE hPalette
, BOOL bForceBackground
)
453 #define PALVERSION 0x0300
455 PLOGPALETTE logPalette
;
456 WORD wNumEntries
= 0;
457 BOOL creationSucceed
;
460 GetObjectA(hPalette
, sizeof(WORD
), &wNumEntries
);
462 if (wNumEntries
== 0) return 0;
464 sizeofPalette
= sizeof(LOGPALETTE
) + ((wNumEntries
-1) * sizeof(PALETTEENTRY
));
465 logPalette
= HeapAlloc( GetProcessHeap(), 0, sizeofPalette
);
467 if (logPalette
== NULL
) return 0;
469 logPalette
->palVersion
= PALVERSION
;
470 logPalette
->palNumEntries
= wNumEntries
;
472 GetPaletteEntries(hPalette
, 0, wNumEntries
, logPalette
->palPalEntry
);
474 creationSucceed
= MFDRV_CreatePalette( dev
, hPalette
, logPalette
, sizeofPalette
);
476 HeapFree( GetProcessHeap(), 0, logPalette
);
484 /***********************************************************************
485 * MFDRV_RealizePalette
487 UINT
MFDRV_RealizePalette(PHYSDEV dev
, HPALETTE hPalette
, BOOL dummy
)
489 char buffer
[sizeof(METARECORD
) - sizeof(WORD
)];
490 METARECORD
*mr
= (METARECORD
*)&buffer
;
492 mr
->rdSize
= (sizeof(METARECORD
) - sizeof(WORD
)) / sizeof(WORD
);
493 mr
->rdFunction
= META_REALIZEPALETTE
;
495 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
)))) return 0;
497 /* The return value is suppose to be the number of entries
498 in the logical palette mapped to the system palette or 0
499 if the function failed. Since it's not trivial here to
500 get that kind of information and since it's of little
501 use in the case of metafiles, we'll always return 1. */