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
] = get_full_gdi_handle( 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
));
180 char buffer
[sizeof(BITMAPINFO
) + 255 * sizeof(RGBQUAD
)]; // ros
182 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
184 BITMAPINFO
*dst_info
, *src_info
= (BITMAPINFO
*)buffer
;
190 if (!get_brush_bitmap_info( hBrush
, src_info
, &bits
, &usage
)) goto done
;
192 info_size
= get_dib_info_size( src_info
, usage
);
193 size
= FIELD_OFFSET( METARECORD
, rdParm
[2] ) + info_size
+ src_info
->bmiHeader
.biSizeImage
;
195 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
196 mr
->rdFunction
= META_DIBCREATEPATTERNBRUSH
;
197 mr
->rdSize
= size
/ 2;
198 mr
->rdParm
[0] = logbrush
.lbStyle
;
199 mr
->rdParm
[1] = usage
;
200 dst_info
= (BITMAPINFO
*)(mr
->rdParm
+ 2);
201 memcpy( dst_info
, src_info
, info_size
);
202 if (dst_info
->bmiHeader
.biClrUsed
== 1 << dst_info
->bmiHeader
.biBitCount
)
203 dst_info
->bmiHeader
.biClrUsed
= 0;
204 dst_ptr
= (char *)dst_info
+ info_size
;
206 /* always return a bottom-up DIB */
207 if (dst_info
->bmiHeader
.biHeight
< 0)
209 int i
, width_bytes
= get_dib_stride( dst_info
->bmiHeader
.biWidth
,
210 dst_info
->bmiHeader
.biBitCount
);
211 dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
212 dst_ptr
+= (dst_info
->bmiHeader
.biHeight
- 1) * width_bytes
;
213 for (i
= 0; i
< dst_info
->bmiHeader
.biHeight
; i
++, dst_ptr
-= width_bytes
)
214 memcpy( dst_ptr
, (char *)bits
+ i
* width_bytes
, width_bytes
);
216 else memcpy( dst_ptr
, bits
, src_info
->bmiHeader
.biSizeImage
);
221 FIXME("Unknown brush style %x\n", logbrush
.lbStyle
);
224 r
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2);
225 HeapFree(GetProcessHeap(), 0, mr
);
229 return MFDRV_AddHandle( dev
, hBrush
);
233 /***********************************************************************
236 HBRUSH
MFDRV_SelectBrush( PHYSDEV dev
, HBRUSH hbrush
, const struct brush_pattern
*pattern
)
240 index
= MFDRV_FindObject(dev
, hbrush
);
243 index
= MFDRV_CreateBrushIndirect( dev
, hbrush
);
246 GDI_hdc_using_object(hbrush
, dev
->hdc
);
248 return MFDRV_SelectObject( dev
, index
) ? hbrush
: 0;
251 /******************************************************************
252 * MFDRV_CreateFontIndirect
255 static UINT16
MFDRV_CreateFontIndirect(PHYSDEV dev
, HFONT hFont
, LOGFONTW
*logfont
)
257 char buffer
[sizeof(METARECORD
) - 2 + sizeof(LOGFONT16
)];
258 METARECORD
*mr
= (METARECORD
*)&buffer
;
262 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(LOGFONT16
) - 2) / 2;
263 mr
->rdFunction
= META_CREATEFONTINDIRECT
;
264 font16
= (LOGFONT16
*)&mr
->rdParm
;
266 font16
->lfHeight
= logfont
->lfHeight
;
267 font16
->lfWidth
= logfont
->lfWidth
;
268 font16
->lfEscapement
= logfont
->lfEscapement
;
269 font16
->lfOrientation
= logfont
->lfOrientation
;
270 font16
->lfWeight
= logfont
->lfWeight
;
271 font16
->lfItalic
= logfont
->lfItalic
;
272 font16
->lfUnderline
= logfont
->lfUnderline
;
273 font16
->lfStrikeOut
= logfont
->lfStrikeOut
;
274 font16
->lfCharSet
= logfont
->lfCharSet
;
275 font16
->lfOutPrecision
= logfont
->lfOutPrecision
;
276 font16
->lfClipPrecision
= logfont
->lfClipPrecision
;
277 font16
->lfQuality
= logfont
->lfQuality
;
278 font16
->lfPitchAndFamily
= logfont
->lfPitchAndFamily
;
279 written
= WideCharToMultiByte( CP_ACP
, 0, logfont
->lfFaceName
, -1, font16
->lfFaceName
, LF_FACESIZE
- 1, NULL
, NULL
);
280 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
281 memset(font16
->lfFaceName
+ written
, 0, LF_FACESIZE
- written
);
283 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
285 return MFDRV_AddHandle( dev
, hFont
);
289 /***********************************************************************
292 HFONT
MFDRV_SelectFont( PHYSDEV dev
, HFONT hfont
, UINT
*aa_flags
)
297 *aa_flags
= GGO_BITMAP
; /* no point in anti-aliasing on metafiles */
298 index
= MFDRV_FindObject(dev
, hfont
);
301 if (!GetObjectW( hfont
, sizeof(font
), &font
))
303 index
= MFDRV_CreateFontIndirect(dev
, hfont
, &font
);
306 GDI_hdc_using_object(hfont
, dev
->hdc
);
308 return MFDRV_SelectObject( dev
, index
) ? hfont
: 0;
311 /******************************************************************
312 * MFDRV_CreatePenIndirect
314 static UINT16
MFDRV_CreatePenIndirect(PHYSDEV dev
, HPEN hPen
, LOGPEN16
*logpen
)
316 char buffer
[sizeof(METARECORD
) - 2 + sizeof(*logpen
)];
317 METARECORD
*mr
= (METARECORD
*)&buffer
;
319 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(*logpen
) - 2) / 2;
320 mr
->rdFunction
= META_CREATEPENINDIRECT
;
321 memcpy(&(mr
->rdParm
), logpen
, sizeof(*logpen
));
322 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
324 return MFDRV_AddHandle( dev
, hPen
);
328 /***********************************************************************
331 HPEN
MFDRV_SelectPen( PHYSDEV dev
, HPEN hpen
, const struct brush_pattern
*pattern
)
336 index
= MFDRV_FindObject(dev
, hpen
);
339 /* must be an extended pen */
340 INT size
= GetObjectW( hpen
, 0, NULL
);
344 if (size
== sizeof(LOGPEN
))
348 GetObjectW( hpen
, sizeof(pen
), &pen
);
349 logpen
.lopnStyle
= pen
.lopnStyle
;
350 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
351 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
352 logpen
.lopnColor
= pen
.lopnColor
;
354 else /* must be an extended pen */
356 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
358 GetObjectW( hpen
, size
, elp
);
359 /* FIXME: add support for user style pens */
360 logpen
.lopnStyle
= elp
->elpPenStyle
;
361 logpen
.lopnWidth
.x
= elp
->elpWidth
;
362 logpen
.lopnWidth
.y
= 0;
363 logpen
.lopnColor
= elp
->elpColor
;
365 HeapFree( GetProcessHeap(), 0, elp
);
368 index
= MFDRV_CreatePenIndirect( dev
, hpen
, &logpen
);
371 GDI_hdc_using_object(hpen
, dev
->hdc
);
373 return MFDRV_SelectObject( dev
, index
) ? hpen
: 0;
377 /******************************************************************
378 * MFDRV_CreatePalette
380 static BOOL
MFDRV_CreatePalette(PHYSDEV dev
, HPALETTE hPalette
, LOGPALETTE
* logPalette
, int sizeofPalette
)
386 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
387 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
388 mr
->rdFunction
= META_CREATEPALETTE
;
389 memcpy(&(mr
->rdParm
), logPalette
, sizeofPalette
);
390 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
))))
392 HeapFree(GetProcessHeap(), 0, mr
);
396 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
397 mr
->rdFunction
= META_SELECTPALETTE
;
399 if ((index
= MFDRV_AddHandle( dev
, hPalette
)) == -1) ret
= FALSE
;
402 *(mr
->rdParm
) = index
;
403 ret
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
));
405 HeapFree(GetProcessHeap(), 0, mr
);
410 /***********************************************************************
411 * MFDRV_SelectPalette
413 HPALETTE
MFDRV_SelectPalette( PHYSDEV dev
, HPALETTE hPalette
, BOOL bForceBackground
)
415 #define PALVERSION 0x0300
417 PLOGPALETTE logPalette
;
418 WORD wNumEntries
= 0;
419 BOOL creationSucceed
;
422 GetObjectA(hPalette
, sizeof(WORD
), &wNumEntries
);
424 if (wNumEntries
== 0) return 0;
426 sizeofPalette
= sizeof(LOGPALETTE
) + ((wNumEntries
-1) * sizeof(PALETTEENTRY
));
427 logPalette
= HeapAlloc( GetProcessHeap(), 0, sizeofPalette
);
429 if (logPalette
== NULL
) return 0;
431 logPalette
->palVersion
= PALVERSION
;
432 logPalette
->palNumEntries
= wNumEntries
;
434 GetPaletteEntries(hPalette
, 0, wNumEntries
, logPalette
->palPalEntry
);
436 creationSucceed
= MFDRV_CreatePalette( dev
, hPalette
, logPalette
, sizeofPalette
);
438 HeapFree( GetProcessHeap(), 0, logPalette
);
446 /***********************************************************************
447 * MFDRV_RealizePalette
449 UINT
MFDRV_RealizePalette(PHYSDEV dev
, HPALETTE hPalette
, BOOL dummy
)
451 char buffer
[sizeof(METARECORD
) - sizeof(WORD
)];
452 METARECORD
*mr
= (METARECORD
*)&buffer
;
454 mr
->rdSize
= (sizeof(METARECORD
) - sizeof(WORD
)) / sizeof(WORD
);
455 mr
->rdFunction
= META_REALIZEPALETTE
;
457 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
)))) return 0;
459 /* The return value is suppose to be the number of entries
460 in the logical palette mapped to the system palette or 0
461 if the function failed. Since it's not trivial here to
462 get that kind of information and since it's of little
463 use in the case of metafiles, we'll always return 1. */