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("Unknown 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
, const struct brush_pattern
*pattern
)
236 index
= MFDRV_FindObject(dev
, hbrush
);
239 index
= MFDRV_CreateBrushIndirect( dev
, hbrush
);
242 GDI_hdc_using_object(hbrush
, dev
->hdc
);
244 return MFDRV_SelectObject( dev
, index
) ? hbrush
: 0;
247 /******************************************************************
248 * MFDRV_CreateFontIndirect
251 static UINT16
MFDRV_CreateFontIndirect(PHYSDEV dev
, HFONT hFont
, LOGFONTW
*logfont
)
253 char buffer
[sizeof(METARECORD
) - 2 + sizeof(LOGFONT16
)];
254 METARECORD
*mr
= (METARECORD
*)&buffer
;
258 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(LOGFONT16
) - 2) / 2;
259 mr
->rdFunction
= META_CREATEFONTINDIRECT
;
260 font16
= (LOGFONT16
*)&mr
->rdParm
;
262 font16
->lfHeight
= logfont
->lfHeight
;
263 font16
->lfWidth
= logfont
->lfWidth
;
264 font16
->lfEscapement
= logfont
->lfEscapement
;
265 font16
->lfOrientation
= logfont
->lfOrientation
;
266 font16
->lfWeight
= logfont
->lfWeight
;
267 font16
->lfItalic
= logfont
->lfItalic
;
268 font16
->lfUnderline
= logfont
->lfUnderline
;
269 font16
->lfStrikeOut
= logfont
->lfStrikeOut
;
270 font16
->lfCharSet
= logfont
->lfCharSet
;
271 font16
->lfOutPrecision
= logfont
->lfOutPrecision
;
272 font16
->lfClipPrecision
= logfont
->lfClipPrecision
;
273 font16
->lfQuality
= logfont
->lfQuality
;
274 font16
->lfPitchAndFamily
= logfont
->lfPitchAndFamily
;
275 written
= WideCharToMultiByte( CP_ACP
, 0, logfont
->lfFaceName
, -1, font16
->lfFaceName
, LF_FACESIZE
- 1, NULL
, NULL
);
276 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
277 memset(font16
->lfFaceName
+ written
, 0, LF_FACESIZE
- written
);
279 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
281 return MFDRV_AddHandle( dev
, hFont
);
285 /***********************************************************************
288 HFONT
MFDRV_SelectFont( PHYSDEV dev
, HFONT hfont
)
293 index
= MFDRV_FindObject(dev
, hfont
);
296 if (!GetObjectW( hfont
, sizeof(font
), &font
))
298 index
= MFDRV_CreateFontIndirect(dev
, hfont
, &font
);
301 GDI_hdc_using_object(hfont
, dev
->hdc
);
303 return MFDRV_SelectObject( dev
, index
) ? hfont
: 0;
306 /******************************************************************
307 * MFDRV_CreatePenIndirect
309 static UINT16
MFDRV_CreatePenIndirect(PHYSDEV dev
, HPEN hPen
, LOGPEN16
*logpen
)
311 char buffer
[sizeof(METARECORD
) - 2 + sizeof(*logpen
)];
312 METARECORD
*mr
= (METARECORD
*)&buffer
;
314 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(*logpen
) - 2) / 2;
315 mr
->rdFunction
= META_CREATEPENINDIRECT
;
316 memcpy(&(mr
->rdParm
), logpen
, sizeof(*logpen
));
317 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
319 return MFDRV_AddHandle( dev
, hPen
);
323 /***********************************************************************
326 HPEN
MFDRV_SelectPen( PHYSDEV dev
, HPEN hpen
, const struct brush_pattern
*pattern
)
331 index
= MFDRV_FindObject(dev
, hpen
);
334 /* must be an extended pen */
335 INT size
= GetObjectW( hpen
, 0, NULL
);
339 if (size
== sizeof(LOGPEN
))
343 GetObjectW( hpen
, sizeof(pen
), &pen
);
344 logpen
.lopnStyle
= pen
.lopnStyle
;
345 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
346 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
347 logpen
.lopnColor
= pen
.lopnColor
;
349 else /* must be an extended pen */
351 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
353 GetObjectW( hpen
, size
, elp
);
354 /* FIXME: add support for user style pens */
355 logpen
.lopnStyle
= elp
->elpPenStyle
;
356 logpen
.lopnWidth
.x
= elp
->elpWidth
;
357 logpen
.lopnWidth
.y
= 0;
358 logpen
.lopnColor
= elp
->elpColor
;
360 HeapFree( GetProcessHeap(), 0, elp
);
363 index
= MFDRV_CreatePenIndirect( dev
, hpen
, &logpen
);
366 GDI_hdc_using_object(hpen
, dev
->hdc
);
368 return MFDRV_SelectObject( dev
, index
) ? hpen
: 0;
372 /******************************************************************
373 * MFDRV_CreatePalette
375 static BOOL
MFDRV_CreatePalette(PHYSDEV dev
, HPALETTE hPalette
, LOGPALETTE
* logPalette
, int sizeofPalette
)
381 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
382 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
383 mr
->rdFunction
= META_CREATEPALETTE
;
384 memcpy(&(mr
->rdParm
), logPalette
, sizeofPalette
);
385 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
))))
387 HeapFree(GetProcessHeap(), 0, mr
);
391 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
392 mr
->rdFunction
= META_SELECTPALETTE
;
394 if ((index
= MFDRV_AddHandle( dev
, hPalette
)) == -1) ret
= FALSE
;
397 *(mr
->rdParm
) = index
;
398 ret
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
));
400 HeapFree(GetProcessHeap(), 0, mr
);
405 /***********************************************************************
406 * MFDRV_SelectPalette
408 HPALETTE
MFDRV_SelectPalette( PHYSDEV dev
, HPALETTE hPalette
, BOOL bForceBackground
)
410 #define PALVERSION 0x0300
412 PLOGPALETTE logPalette
;
413 WORD wNumEntries
= 0;
414 BOOL creationSucceed
;
417 GetObjectA(hPalette
, sizeof(WORD
), &wNumEntries
);
419 if (wNumEntries
== 0) return 0;
421 sizeofPalette
= sizeof(LOGPALETTE
) + ((wNumEntries
-1) * sizeof(PALETTEENTRY
));
422 logPalette
= HeapAlloc( GetProcessHeap(), 0, sizeofPalette
);
424 if (logPalette
== NULL
) return 0;
426 logPalette
->palVersion
= PALVERSION
;
427 logPalette
->palNumEntries
= wNumEntries
;
429 GetPaletteEntries(hPalette
, 0, wNumEntries
, logPalette
->palPalEntry
);
431 creationSucceed
= MFDRV_CreatePalette( dev
, hPalette
, logPalette
, sizeofPalette
);
433 HeapFree( GetProcessHeap(), 0, logPalette
);
441 /***********************************************************************
442 * MFDRV_RealizePalette
444 UINT
MFDRV_RealizePalette(PHYSDEV dev
, HPALETTE hPalette
, BOOL dummy
)
446 char buffer
[sizeof(METARECORD
) - sizeof(WORD
)];
447 METARECORD
*mr
= (METARECORD
*)&buffer
;
449 mr
->rdSize
= (sizeof(METARECORD
) - sizeof(WORD
)) / sizeof(WORD
);
450 mr
->rdFunction
= META_REALIZEPALETTE
;
452 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
)))) return 0;
454 /* The return value is suppose to be the number of entries
455 in the logical palette mapped to the system palette or 0
456 if the function failed. Since it's not trivial here to
457 get that kind of information and since it's of little
458 use in the case of metafiles, we'll always return 1. */