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
));
179 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
180 BITMAPINFO
*dst_info
, *src_info
= (BITMAPINFO
*)buffer
;
186 if (!get_brush_bitmap_info( hBrush
, src_info
, &bits
, &usage
)) goto done
;
188 info_size
= get_dib_info_size( src_info
, usage
);
189 size
= FIELD_OFFSET( METARECORD
, rdParm
[2] ) + info_size
+ src_info
->bmiHeader
.biSizeImage
;
191 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
192 mr
->rdFunction
= META_DIBCREATEPATTERNBRUSH
;
193 mr
->rdSize
= size
/ 2;
194 mr
->rdParm
[0] = logbrush
.lbStyle
;
195 mr
->rdParm
[1] = usage
;
196 dst_info
= (BITMAPINFO
*)(mr
->rdParm
+ 2);
197 memcpy( dst_info
, src_info
, info_size
);
198 if (dst_info
->bmiHeader
.biClrUsed
== 1 << dst_info
->bmiHeader
.biBitCount
)
199 dst_info
->bmiHeader
.biClrUsed
= 0;
200 dst_ptr
= (char *)dst_info
+ info_size
;
202 /* always return a bottom-up DIB */
203 if (dst_info
->bmiHeader
.biHeight
< 0)
205 int i
, width_bytes
= get_dib_stride( dst_info
->bmiHeader
.biWidth
,
206 dst_info
->bmiHeader
.biBitCount
);
207 dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
208 dst_ptr
+= (dst_info
->bmiHeader
.biHeight
- 1) * width_bytes
;
209 for (i
= 0; i
< dst_info
->bmiHeader
.biHeight
; i
++, dst_ptr
-= width_bytes
)
210 memcpy( dst_ptr
, (char *)bits
+ i
* width_bytes
, width_bytes
);
212 else memcpy( dst_ptr
, bits
, src_info
->bmiHeader
.biSizeImage
);
217 FIXME("Unkonwn brush style %x\n", logbrush
.lbStyle
);
220 r
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2);
221 HeapFree(GetProcessHeap(), 0, mr
);
225 return MFDRV_AddHandle( dev
, hBrush
);
229 /***********************************************************************
232 HBRUSH
MFDRV_SelectBrush( PHYSDEV dev
, HBRUSH hbrush
, HBITMAP bitmap
,
233 const BITMAPINFO
*info
, void *bits
, UINT usage
)
237 index
= MFDRV_FindObject(dev
, hbrush
);
240 index
= MFDRV_CreateBrushIndirect( dev
, hbrush
);
243 GDI_hdc_using_object(hbrush
, dev
->hdc
);
245 return MFDRV_SelectObject( dev
, index
) ? hbrush
: 0;
248 /******************************************************************
249 * MFDRV_CreateFontIndirect
252 static UINT16
MFDRV_CreateFontIndirect(PHYSDEV dev
, HFONT hFont
, LOGFONTW
*logfont
)
254 char buffer
[sizeof(METARECORD
) - 2 + sizeof(LOGFONT16
)];
255 METARECORD
*mr
= (METARECORD
*)&buffer
;
259 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(LOGFONT16
) - 2) / 2;
260 mr
->rdFunction
= META_CREATEFONTINDIRECT
;
261 font16
= (LOGFONT16
*)&mr
->rdParm
;
263 font16
->lfHeight
= logfont
->lfHeight
;
264 font16
->lfWidth
= logfont
->lfWidth
;
265 font16
->lfEscapement
= logfont
->lfEscapement
;
266 font16
->lfOrientation
= logfont
->lfOrientation
;
267 font16
->lfWeight
= logfont
->lfWeight
;
268 font16
->lfItalic
= logfont
->lfItalic
;
269 font16
->lfUnderline
= logfont
->lfUnderline
;
270 font16
->lfStrikeOut
= logfont
->lfStrikeOut
;
271 font16
->lfCharSet
= logfont
->lfCharSet
;
272 font16
->lfOutPrecision
= logfont
->lfOutPrecision
;
273 font16
->lfClipPrecision
= logfont
->lfClipPrecision
;
274 font16
->lfQuality
= logfont
->lfQuality
;
275 font16
->lfPitchAndFamily
= logfont
->lfPitchAndFamily
;
276 written
= WideCharToMultiByte( CP_ACP
, 0, logfont
->lfFaceName
, -1, font16
->lfFaceName
, LF_FACESIZE
- 1, NULL
, NULL
);
277 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
278 memset(font16
->lfFaceName
+ written
, 0, LF_FACESIZE
- written
);
280 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
282 return MFDRV_AddHandle( dev
, hFont
);
286 /***********************************************************************
289 HFONT
MFDRV_SelectFont( PHYSDEV dev
, HFONT hfont
)
294 index
= MFDRV_FindObject(dev
, hfont
);
297 if (!GetObjectW( hfont
, sizeof(font
), &font
))
299 index
= MFDRV_CreateFontIndirect(dev
, hfont
, &font
);
302 GDI_hdc_using_object(hfont
, dev
->hdc
);
304 return MFDRV_SelectObject( dev
, index
) ? hfont
: 0;
307 /******************************************************************
308 * MFDRV_CreatePenIndirect
310 static UINT16
MFDRV_CreatePenIndirect(PHYSDEV dev
, HPEN hPen
, LOGPEN16
*logpen
)
312 char buffer
[sizeof(METARECORD
) - 2 + sizeof(*logpen
)];
313 METARECORD
*mr
= (METARECORD
*)&buffer
;
315 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(*logpen
) - 2) / 2;
316 mr
->rdFunction
= META_CREATEPENINDIRECT
;
317 memcpy(&(mr
->rdParm
), logpen
, sizeof(*logpen
));
318 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
320 return MFDRV_AddHandle( dev
, hPen
);
324 /***********************************************************************
327 HPEN
MFDRV_SelectPen( PHYSDEV dev
, HPEN hpen
)
332 index
= MFDRV_FindObject(dev
, hpen
);
335 /* must be an extended pen */
336 INT size
= GetObjectW( hpen
, 0, NULL
);
340 if (size
== sizeof(LOGPEN
))
344 GetObjectW( hpen
, sizeof(pen
), &pen
);
345 logpen
.lopnStyle
= pen
.lopnStyle
;
346 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
347 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
348 logpen
.lopnColor
= pen
.lopnColor
;
350 else /* must be an extended pen */
352 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
354 GetObjectW( hpen
, size
, elp
);
355 /* FIXME: add support for user style pens */
356 logpen
.lopnStyle
= elp
->elpPenStyle
;
357 logpen
.lopnWidth
.x
= elp
->elpWidth
;
358 logpen
.lopnWidth
.y
= 0;
359 logpen
.lopnColor
= elp
->elpColor
;
361 HeapFree( GetProcessHeap(), 0, elp
);
364 index
= MFDRV_CreatePenIndirect( dev
, hpen
, &logpen
);
367 GDI_hdc_using_object(hpen
, dev
->hdc
);
369 return MFDRV_SelectObject( dev
, index
) ? hpen
: 0;
373 /******************************************************************
374 * MFDRV_CreatePalette
376 static BOOL
MFDRV_CreatePalette(PHYSDEV dev
, HPALETTE hPalette
, LOGPALETTE
* logPalette
, int sizeofPalette
)
382 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
383 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
384 mr
->rdFunction
= META_CREATEPALETTE
;
385 memcpy(&(mr
->rdParm
), logPalette
, sizeofPalette
);
386 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
))))
388 HeapFree(GetProcessHeap(), 0, mr
);
392 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
393 mr
->rdFunction
= META_SELECTPALETTE
;
395 if ((index
= MFDRV_AddHandle( dev
, hPalette
)) == -1) ret
= FALSE
;
398 *(mr
->rdParm
) = index
;
399 ret
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
));
401 HeapFree(GetProcessHeap(), 0, mr
);
406 /***********************************************************************
407 * MFDRV_SelectPalette
409 HPALETTE
MFDRV_SelectPalette( PHYSDEV dev
, HPALETTE hPalette
, BOOL bForceBackground
)
411 #define PALVERSION 0x0300
413 PLOGPALETTE logPalette
;
414 WORD wNumEntries
= 0;
415 BOOL creationSucceed
;
418 GetObjectA(hPalette
, sizeof(WORD
), &wNumEntries
);
420 if (wNumEntries
== 0) return 0;
422 sizeofPalette
= sizeof(LOGPALETTE
) + ((wNumEntries
-1) * sizeof(PALETTEENTRY
));
423 logPalette
= HeapAlloc( GetProcessHeap(), 0, sizeofPalette
);
425 if (logPalette
== NULL
) return 0;
427 logPalette
->palVersion
= PALVERSION
;
428 logPalette
->palNumEntries
= wNumEntries
;
430 GetPaletteEntries(hPalette
, 0, wNumEntries
, logPalette
->palPalEntry
);
432 creationSucceed
= MFDRV_CreatePalette( dev
, hPalette
, logPalette
, sizeofPalette
);
434 HeapFree( GetProcessHeap(), 0, logPalette
);
442 /***********************************************************************
443 * MFDRV_RealizePalette
445 UINT
MFDRV_RealizePalette(PHYSDEV dev
, HPALETTE hPalette
, BOOL dummy
)
447 char buffer
[sizeof(METARECORD
) - sizeof(WORD
)];
448 METARECORD
*mr
= (METARECORD
*)&buffer
;
450 mr
->rdSize
= (sizeof(METARECORD
) - sizeof(WORD
)) / sizeof(WORD
);
451 mr
->rdFunction
= META_REALIZEPALETTE
;
453 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
)))) return 0;
455 /* The return value is suppose to be the number of entries
456 in the logical palette mapped to the system palette or 0
457 if the function failed. Since it's not trivial here to
458 get that kind of information and since it's of little
459 use in the case of metafiles, we'll always return 1. */