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
));
179 char buffer
[sizeof(BITMAPINFO
) + 255 * sizeof(RGBQUAD
)]; // ros
180 //char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
181 BITMAPINFO
*dst_info
, *src_info
= (BITMAPINFO
*)buffer
;
187 if (!get_brush_bitmap_info( hBrush
, src_info
, &bits
, &usage
)) goto done
;
189 info_size
= get_dib_info_size( src_info
, usage
);
190 size
= FIELD_OFFSET( METARECORD
, rdParm
[2] ) + info_size
+ src_info
->bmiHeader
.biSizeImage
;
192 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
193 mr
->rdFunction
= META_DIBCREATEPATTERNBRUSH
;
194 mr
->rdSize
= size
/ 2;
195 mr
->rdParm
[0] = logbrush
.lbStyle
;
196 mr
->rdParm
[1] = usage
;
197 dst_info
= (BITMAPINFO
*)(mr
->rdParm
+ 2);
198 memcpy( dst_info
, src_info
, info_size
);
199 if (dst_info
->bmiHeader
.biClrUsed
== 1 << dst_info
->bmiHeader
.biBitCount
)
200 dst_info
->bmiHeader
.biClrUsed
= 0;
201 dst_ptr
= (char *)dst_info
+ info_size
;
203 /* always return a bottom-up DIB */
204 if (dst_info
->bmiHeader
.biHeight
< 0)
206 int i
, width_bytes
= get_dib_stride( dst_info
->bmiHeader
.biWidth
,
207 dst_info
->bmiHeader
.biBitCount
);
208 dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
209 dst_ptr
+= (dst_info
->bmiHeader
.biHeight
- 1) * width_bytes
;
210 for (i
= 0; i
< dst_info
->bmiHeader
.biHeight
; i
++, dst_ptr
-= width_bytes
)
211 memcpy( dst_ptr
, (char *)bits
+ i
* width_bytes
, width_bytes
);
213 else memcpy( dst_ptr
, bits
, src_info
->bmiHeader
.biSizeImage
);
218 FIXME("Unknown brush style %x\n", logbrush
.lbStyle
);
221 r
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2);
222 HeapFree(GetProcessHeap(), 0, mr
);
226 return MFDRV_AddHandle( dev
, hBrush
);
230 /***********************************************************************
233 HBRUSH
MFDRV_SelectBrush( PHYSDEV dev
, HBRUSH hbrush
, const struct brush_pattern
*pattern
)
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
, UINT
*aa_flags
)
294 *aa_flags
= GGO_BITMAP
; /* no point in anti-aliasing on metafiles */
295 index
= MFDRV_FindObject(dev
, hfont
);
298 if (!GetObjectW( hfont
, sizeof(font
), &font
))
300 index
= MFDRV_CreateFontIndirect(dev
, hfont
, &font
);
303 GDI_hdc_using_object(hfont
, dev
->hdc
);
305 return MFDRV_SelectObject( dev
, index
) ? hfont
: 0;
308 /******************************************************************
309 * MFDRV_CreatePenIndirect
311 static UINT16
MFDRV_CreatePenIndirect(PHYSDEV dev
, HPEN hPen
, LOGPEN16
*logpen
)
313 char buffer
[sizeof(METARECORD
) - 2 + sizeof(*logpen
)];
314 METARECORD
*mr
= (METARECORD
*)&buffer
;
316 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(*logpen
) - 2) / 2;
317 mr
->rdFunction
= META_CREATEPENINDIRECT
;
318 memcpy(&(mr
->rdParm
), logpen
, sizeof(*logpen
));
319 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* 2)))
321 return MFDRV_AddHandle( dev
, hPen
);
325 /***********************************************************************
328 HPEN
MFDRV_SelectPen( PHYSDEV dev
, HPEN hpen
, const struct brush_pattern
*pattern
)
333 index
= MFDRV_FindObject(dev
, hpen
);
336 /* must be an extended pen */
337 INT size
= GetObjectW( hpen
, 0, NULL
);
341 if (size
== sizeof(LOGPEN
))
345 GetObjectW( hpen
, sizeof(pen
), &pen
);
346 logpen
.lopnStyle
= pen
.lopnStyle
;
347 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
348 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
349 logpen
.lopnColor
= pen
.lopnColor
;
351 else /* must be an extended pen */
353 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
355 GetObjectW( hpen
, size
, elp
);
356 /* FIXME: add support for user style pens */
357 logpen
.lopnStyle
= elp
->elpPenStyle
;
358 logpen
.lopnWidth
.x
= elp
->elpWidth
;
359 logpen
.lopnWidth
.y
= 0;
360 logpen
.lopnColor
= elp
->elpColor
;
362 HeapFree( GetProcessHeap(), 0, elp
);
365 index
= MFDRV_CreatePenIndirect( dev
, hpen
, &logpen
);
368 GDI_hdc_using_object(hpen
, dev
->hdc
);
370 return MFDRV_SelectObject( dev
, index
) ? hpen
: 0;
374 /******************************************************************
375 * MFDRV_CreatePalette
377 static BOOL
MFDRV_CreatePalette(PHYSDEV dev
, HPALETTE hPalette
, LOGPALETTE
* logPalette
, int sizeofPalette
)
383 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
384 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
385 mr
->rdFunction
= META_CREATEPALETTE
;
386 memcpy(&(mr
->rdParm
), logPalette
, sizeofPalette
);
387 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
))))
389 HeapFree(GetProcessHeap(), 0, mr
);
393 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
394 mr
->rdFunction
= META_SELECTPALETTE
;
396 if ((index
= MFDRV_AddHandle( dev
, hPalette
)) == -1) ret
= FALSE
;
399 *(mr
->rdParm
) = index
;
400 ret
= MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
));
402 HeapFree(GetProcessHeap(), 0, mr
);
407 /***********************************************************************
408 * MFDRV_SelectPalette
410 HPALETTE
MFDRV_SelectPalette( PHYSDEV dev
, HPALETTE hPalette
, BOOL bForceBackground
)
412 #define PALVERSION 0x0300
414 PLOGPALETTE logPalette
;
415 WORD wNumEntries
= 0;
416 BOOL creationSucceed
;
419 GetObjectA(hPalette
, sizeof(WORD
), &wNumEntries
);
421 if (wNumEntries
== 0) return 0;
423 sizeofPalette
= sizeof(LOGPALETTE
) + ((wNumEntries
-1) * sizeof(PALETTEENTRY
));
424 logPalette
= HeapAlloc( GetProcessHeap(), 0, sizeofPalette
);
426 if (logPalette
== NULL
) return 0;
428 logPalette
->palVersion
= PALVERSION
;
429 logPalette
->palNumEntries
= wNumEntries
;
431 GetPaletteEntries(hPalette
, 0, wNumEntries
, logPalette
->palPalEntry
);
433 creationSucceed
= MFDRV_CreatePalette( dev
, hPalette
, logPalette
, sizeofPalette
);
435 HeapFree( GetProcessHeap(), 0, logPalette
);
443 /***********************************************************************
444 * MFDRV_RealizePalette
446 UINT
MFDRV_RealizePalette(PHYSDEV dev
, HPALETTE hPalette
, BOOL dummy
)
448 char buffer
[sizeof(METARECORD
) - sizeof(WORD
)];
449 METARECORD
*mr
= (METARECORD
*)&buffer
;
451 mr
->rdSize
= (sizeof(METARECORD
) - sizeof(WORD
)) / sizeof(WORD
);
452 mr
->rdFunction
= META_REALIZEPALETTE
;
454 if (!(MFDRV_WriteRecord( dev
, mr
, mr
->rdSize
* sizeof(WORD
)))) return 0;
456 /* The return value is suppose to be the number of entries
457 in the logical palette mapped to the system palette or 0
458 if the function failed. Since it's not trivial here to
459 get that kind of information and since it's of little
460 use in the case of metafiles, we'll always return 1. */