2 * Metafile DC functions
4 * Copyright 1999 Huw D M Davies
5 * Copyright 1993, 1994, 1996 Alexandre Julliard
6 * Copyright 2021 Jacek Caban for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "gdi_private.h"
27 #include "wine/wingdi16.h"
29 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
37 METAHEADER
*mh
; /* Pointer to metafile header */
38 UINT handles_size
, cur_handles
;
40 HANDLE hFile
; /* Handle for disk based MetaFile */
46 #define HANDLE_LIST_INC 20
48 struct metadc
*get_metadc_ptr( HDC hdc
)
50 struct metadc
*metafile
= get_gdi_client_ptr( hdc
, NTGDI_OBJ_METADC
);
51 if (!metafile
) SetLastError( ERROR_INVALID_HANDLE
);
55 static BOOL
metadc_write_record( struct metadc
*metadc
, METARECORD
*mr
, unsigned int rlen
)
60 len
= metadc
->mh
->mtSize
* sizeof(WORD
) + rlen
;
61 size
= HeapSize( GetProcessHeap(), 0, metadc
->mh
);
64 size
+= size
/ sizeof(WORD
) + rlen
;
65 mh
= HeapReAlloc( GetProcessHeap(), 0, metadc
->mh
, size
);
66 if (!mh
) return FALSE
;
69 memcpy( (WORD
*)metadc
->mh
+ metadc
->mh
->mtSize
, mr
, rlen
);
71 metadc
->mh
->mtSize
+= rlen
/ sizeof(WORD
);
72 metadc
->mh
->mtMaxRecord
= max( metadc
->mh
->mtMaxRecord
, rlen
/ sizeof(WORD
) );
76 static BOOL
metadc_record( HDC hdc
, METARECORD
*mr
, DWORD rlen
)
78 struct metadc
*metadc
;
80 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
81 return metadc_write_record( metadc
, mr
, rlen
);
84 static BOOL
metadc_param0( HDC hdc
, short func
)
88 mr
.rdSize
= FIELD_OFFSET(METARECORD
, rdParm
[0]) / sizeof(WORD
);
90 return metadc_record( hdc
, &mr
, mr
.rdSize
* sizeof(WORD
) );
93 static BOOL
metadc_param1( HDC hdc
, short func
, short param
)
97 mr
.rdSize
= sizeof(mr
) / sizeof(WORD
);
100 return metadc_record( hdc
, &mr
, mr
.rdSize
* sizeof(WORD
) );
103 static BOOL
metadc_param2( HDC hdc
, short func
, short param1
, short param2
)
105 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[2])];
106 METARECORD
*mr
= (METARECORD
*)&buffer
;
108 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
109 mr
->rdFunction
= func
;
110 mr
->rdParm
[0] = param2
;
111 mr
->rdParm
[1] = param1
;
112 return metadc_record( hdc
, mr
, sizeof(buffer
) );
115 static BOOL
metadc_param4( HDC hdc
, short func
, short param1
, short param2
,
116 short param3
, short param4
)
118 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[4])];
119 METARECORD
*mr
= (METARECORD
*)&buffer
;
121 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
122 mr
->rdFunction
= func
;
123 mr
->rdParm
[0] = param4
;
124 mr
->rdParm
[1] = param3
;
125 mr
->rdParm
[2] = param2
;
126 mr
->rdParm
[3] = param1
;
127 return metadc_record( hdc
, mr
, sizeof(buffer
) );
130 static BOOL
metadc_param5( HDC hdc
, short func
, short param1
, short param2
,
131 short param3
, short param4
, short param5
)
133 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[5])];
134 METARECORD
*mr
= (METARECORD
*)&buffer
;
136 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
137 mr
->rdFunction
= func
;
138 mr
->rdParm
[0] = param5
;
139 mr
->rdParm
[1] = param4
;
140 mr
->rdParm
[2] = param3
;
141 mr
->rdParm
[3] = param2
;
142 mr
->rdParm
[4] = param1
;
143 return metadc_record( hdc
, mr
, sizeof(buffer
) );
146 static BOOL
metadc_param6( HDC hdc
, short func
, short param1
, short param2
,
147 short param3
, short param4
, short param5
,
150 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[6])];
151 METARECORD
*mr
= (METARECORD
*)&buffer
;
153 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
154 mr
->rdFunction
= func
;
155 mr
->rdParm
[0] = param6
;
156 mr
->rdParm
[1] = param5
;
157 mr
->rdParm
[2] = param4
;
158 mr
->rdParm
[3] = param3
;
159 mr
->rdParm
[4] = param2
;
160 mr
->rdParm
[5] = param1
;
161 return metadc_record( hdc
, mr
, sizeof(buffer
) );
164 static BOOL
metadc_param8( HDC hdc
, short func
, short param1
, short param2
,
165 short param3
, short param4
, short param5
,
166 short param6
, short param7
, short param8
)
168 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[8])];
169 METARECORD
*mr
= (METARECORD
*)&buffer
;
171 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
172 mr
->rdFunction
= func
;
173 mr
->rdParm
[0] = param8
;
174 mr
->rdParm
[1] = param7
;
175 mr
->rdParm
[2] = param6
;
176 mr
->rdParm
[3] = param5
;
177 mr
->rdParm
[4] = param4
;
178 mr
->rdParm
[5] = param3
;
179 mr
->rdParm
[6] = param2
;
180 mr
->rdParm
[7] = param1
;
181 return metadc_record( hdc
, mr
, sizeof(buffer
) );
184 BOOL
METADC_SaveDC( HDC hdc
)
186 return metadc_param0( hdc
, META_SAVEDC
);
189 BOOL
METADC_RestoreDC( HDC hdc
, INT level
)
191 return metadc_param1( hdc
, META_RESTOREDC
, level
);
194 BOOL
METADC_SetTextAlign( HDC hdc
, UINT align
)
196 return metadc_param2( hdc
, META_SETTEXTALIGN
, HIWORD(align
), LOWORD(align
) );
199 BOOL
METADC_SetBkMode( HDC hdc
, INT mode
)
201 return metadc_param1( hdc
, META_SETBKMODE
, (WORD
)mode
);
204 BOOL
METADC_SetBkColor( HDC hdc
, COLORREF color
)
206 return metadc_param2( hdc
, META_SETBKCOLOR
, HIWORD(color
), LOWORD(color
) );
209 BOOL
METADC_SetTextColor( HDC hdc
, COLORREF color
)
211 return metadc_param2( hdc
, META_SETTEXTCOLOR
, HIWORD(color
), LOWORD(color
) );
214 BOOL
METADC_SetROP2( HDC hdc
, INT rop
)
216 return metadc_param1( hdc
, META_SETROP2
, (WORD
)rop
);
219 BOOL
METADC_SetRelAbs( HDC hdc
, INT mode
)
221 return metadc_param1( hdc
, META_SETRELABS
, (WORD
)mode
);
224 BOOL
METADC_SetPolyFillMode( HDC hdc
, INT mode
)
226 return metadc_param1( hdc
, META_SETPOLYFILLMODE
, mode
);
229 BOOL
METADC_SetStretchBltMode( HDC hdc
, INT mode
)
231 return metadc_param1( hdc
, META_SETSTRETCHBLTMODE
, mode
);
234 BOOL
METADC_IntersectClipRect( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
236 return metadc_param4( hdc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
239 BOOL
METADC_ExcludeClipRect( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
241 return metadc_param4( hdc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
244 BOOL
METADC_OffsetClipRgn( HDC hdc
, INT x
, INT y
)
246 return metadc_param2( hdc
, META_OFFSETCLIPRGN
, x
, y
);
249 BOOL
METADC_SetLayout( HDC hdc
, DWORD layout
)
251 return metadc_param2( hdc
, META_SETLAYOUT
, HIWORD(layout
), LOWORD(layout
) );
254 BOOL
METADC_SetMapMode( HDC hdc
, INT mode
)
256 return metadc_param1( hdc
, META_SETMAPMODE
, mode
);
259 BOOL
METADC_SetViewportExtEx( HDC hdc
, INT x
, INT y
)
261 return metadc_param2( hdc
, META_SETVIEWPORTEXT
, x
, y
);
264 BOOL
METADC_SetViewportOrgEx( HDC hdc
, INT x
, INT y
)
266 return metadc_param2( hdc
, META_SETVIEWPORTORG
, x
, y
);
269 BOOL
METADC_SetWindowExtEx( HDC hdc
, INT x
, INT y
)
271 return metadc_param2( hdc
, META_SETWINDOWEXT
, x
, y
);
274 BOOL
METADC_SetWindowOrgEx( HDC hdc
, INT x
, INT y
)
276 return metadc_param2( hdc
, META_SETWINDOWORG
, x
, y
);
279 BOOL
METADC_OffsetViewportOrgEx( HDC hdc
, INT x
, INT y
)
281 return metadc_param2( hdc
, META_OFFSETVIEWPORTORG
, x
, y
);
284 BOOL
METADC_OffsetWindowOrgEx( HDC hdc
, INT x
, INT y
)
286 return metadc_param2( hdc
, META_OFFSETWINDOWORG
, x
, y
);
289 BOOL
METADC_ScaleViewportExtEx( HDC hdc
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
)
291 return metadc_param4( hdc
, META_SCALEVIEWPORTEXT
, x_num
, x_denom
, y_num
, y_denom
);
294 BOOL
METADC_ScaleWindowExtEx( HDC hdc
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
)
296 return metadc_param4( hdc
, META_SCALEWINDOWEXT
, x_num
, x_denom
, y_num
, y_denom
);
299 BOOL
METADC_SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
301 return metadc_param2( hdc
, META_SETTEXTJUSTIFICATION
, extra
, breaks
);
304 BOOL
METADC_SetTextCharacterExtra( HDC hdc
, INT extra
)
306 return metadc_param1( hdc
, META_SETTEXTCHAREXTRA
, extra
);
309 BOOL
METADC_SetMapperFlags( HDC hdc
, DWORD flags
)
311 return metadc_param2( hdc
, META_SETMAPPERFLAGS
, HIWORD(flags
), LOWORD(flags
) );
314 BOOL
METADC_MoveTo( HDC hdc
, INT x
, INT y
)
316 return metadc_param2( hdc
, META_MOVETO
, x
, y
);
319 BOOL
METADC_LineTo( HDC hdc
, INT x
, INT y
)
321 return metadc_param2( hdc
, META_LINETO
, x
, y
);
324 BOOL
METADC_Arc( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
325 INT xstart
, INT ystart
, INT xend
, INT yend
)
327 return metadc_param8( hdc
, META_ARC
, left
, top
, right
, bottom
,
328 xstart
, ystart
, xend
, yend
);
331 BOOL
METADC_Pie( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
332 INT xstart
, INT ystart
, INT xend
, INT yend
)
334 return metadc_param8( hdc
, META_PIE
, left
, top
, right
, bottom
,
335 xstart
, ystart
, xend
, yend
);
338 BOOL
METADC_Chord( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
339 INT xstart
, INT ystart
, INT xend
, INT yend
)
341 return metadc_param8( hdc
, META_CHORD
, left
, top
, right
, bottom
,
342 xstart
, ystart
, xend
, yend
);
345 BOOL
METADC_Ellipse( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
347 return metadc_param4( hdc
, META_ELLIPSE
, left
, top
, right
, bottom
);
350 BOOL
METADC_Rectangle( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
352 return metadc_param4( hdc
, META_RECTANGLE
, left
, top
, right
, bottom
);
355 BOOL
METADC_RoundRect( HDC hdc
, INT left
, INT top
, INT right
,
356 INT bottom
, INT ell_width
, INT ell_height
)
358 return metadc_param6( hdc
, META_ROUNDRECT
, left
, top
, right
, bottom
,
359 ell_width
, ell_height
);
362 BOOL
METADC_SetPixel( HDC hdc
, INT x
, INT y
, COLORREF color
)
364 return metadc_param4( hdc
, META_SETPIXEL
, x
, y
, HIWORD(color
), LOWORD(color
) );
367 static BOOL
metadc_poly( HDC hdc
, short func
, POINTS
*pt
, short count
)
373 len
= sizeof(METARECORD
) + count
* 4;
374 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
)))
377 mr
->rdSize
= len
/ 2;
378 mr
->rdFunction
= func
;
379 *(mr
->rdParm
) = count
;
380 memcpy(mr
->rdParm
+ 1, pt
, count
* 4);
381 ret
= metadc_record( hdc
, mr
, mr
->rdSize
* 2);
382 HeapFree( GetProcessHeap(), 0, mr
);
386 BOOL
METADC_Polyline( HDC hdc
, const POINT
*pt
, INT count
)
392 pts
= HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS
) * count
);
393 if(!pts
) return FALSE
;
399 ret
= metadc_poly( hdc
, META_POLYLINE
, pts
, count
);
401 HeapFree( GetProcessHeap(), 0, pts
);
405 BOOL
METADC_Polygon( HDC hdc
, const POINT
*pt
, INT count
)
411 pts
= HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS
) * count
);
412 if(!pts
) return FALSE
;
413 for (i
= count
; i
--;)
418 ret
= metadc_poly( hdc
, META_POLYGON
, pts
, count
);
420 HeapFree( GetProcessHeap(), 0, pts
);
424 BOOL
METADC_PolyPolygon( HDC hdc
, const POINT
*pt
, const INT
*counts
, UINT polygons
)
431 INT16 totalpoint16
= 0;
434 for (i
= 0; i
< polygons
; i
++)
435 totalpoint16
+= counts
[i
];
437 /* allocate space for all points */
438 pts
=HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS
) * totalpoint16
);
439 pointcounts
= HeapAlloc( GetProcessHeap(), 0, sizeof(INT16
) * totalpoint16
);
441 /* copy point counts */
442 for (i
= 0; i
< polygons
; i
++)
443 pointcounts
[i
] = counts
[i
];
445 /* convert all points */
446 for (j
= totalpoint16
; j
--;)
452 len
= sizeof(METARECORD
) + sizeof(WORD
) + polygons
* sizeof(INT16
) +
453 totalpoint16
* sizeof(*pts
);
455 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
)))
457 HeapFree( GetProcessHeap(), 0, pts
);
458 HeapFree( GetProcessHeap(), 0, pointcounts
);
462 mr
->rdSize
= len
/ sizeof(WORD
);
463 mr
->rdFunction
= META_POLYPOLYGON
;
464 *mr
->rdParm
= polygons
;
465 memcpy( mr
->rdParm
+ 1, pointcounts
, polygons
* sizeof(INT16
) );
466 memcpy( mr
->rdParm
+ 1+polygons
, pts
, totalpoint16
* sizeof(*pts
) );
467 ret
= metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
469 HeapFree( GetProcessHeap(), 0, pts
);
470 HeapFree( GetProcessHeap(), 0, pointcounts
);
471 HeapFree( GetProcessHeap(), 0, mr
);
475 BOOL
METADC_ExtFloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
, UINT fill_type
)
477 return metadc_param5( hdc
, META_EXTFLOODFILL
, x
, y
, HIWORD(color
), LOWORD(color
), fill_type
);
480 static UINT
metadc_add_handle( struct metadc
*metadc
, HGDIOBJ obj
)
484 for (index
= 0; index
< metadc
->handles_size
; index
++)
485 if (metadc
->handles
[index
] == 0) break;
486 if(index
== metadc
->handles_size
)
488 metadc
->handles_size
+= HANDLE_LIST_INC
;
489 metadc
->handles
= HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
491 metadc
->handles_size
* sizeof(metadc
->handles
[0]) );
493 metadc
->handles
[index
] = obj
;
495 metadc
->cur_handles
++;
496 if (metadc
->cur_handles
> metadc
->mh
->mtNoObjects
)
497 metadc
->mh
->mtNoObjects
++;
499 return index
; /* index 0 is not reserved for metafiles */
502 static BOOL
metadc_remove_handle( struct metadc
*metadc
, UINT index
)
506 if (index
< metadc
->handles_size
&& metadc
->handles
[index
])
508 metadc
->handles
[index
] = 0;
509 metadc
->cur_handles
--;
515 static INT16
metadc_create_brush( struct metadc
*metadc
, HBRUSH brush
)
522 if (!GetObjectA( brush
, sizeof(logbrush
), &logbrush
)) return -1;
524 switch (logbrush
.lbStyle
)
532 lb16
.lbStyle
= logbrush
.lbStyle
;
533 lb16
.lbColor
= logbrush
.lbColor
;
534 lb16
.lbHatch
= logbrush
.lbHatch
;
535 size
= sizeof(METARECORD
) + sizeof(LOGBRUSH16
) - sizeof(WORD
);
536 mr
= HeapAlloc( GetProcessHeap(), 0, size
);
537 mr
->rdSize
= size
/ sizeof(WORD
);
538 mr
->rdFunction
= META_CREATEBRUSHINDIRECT
;
539 memcpy( mr
->rdParm
, &lb16
, sizeof(LOGBRUSH16
) );
545 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
546 BITMAPINFO
*dst_info
, *src_info
= (BITMAPINFO
*)buffer
;
550 if (!NtGdiIcmBrushInfo( 0, brush
, src_info
, NULL
, NULL
, &usage
, NULL
, 0 ))
553 info_size
= get_dib_info_size( src_info
, usage
);
554 size
= FIELD_OFFSET( METARECORD
, rdParm
[2] ) +
555 info_size
+ src_info
->bmiHeader
.biSizeImage
;
557 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
558 mr
->rdFunction
= META_DIBCREATEPATTERNBRUSH
;
559 mr
->rdSize
= size
/ sizeof(WORD
);
560 mr
->rdParm
[0] = logbrush
.lbStyle
;
561 mr
->rdParm
[1] = usage
;
562 dst_info
= (BITMAPINFO
*)(mr
->rdParm
+ 2);
563 NtGdiIcmBrushInfo( 0, brush
, dst_info
, (char *)dst_info
+ info_size
, NULL
, NULL
, NULL
, 0 );
564 if (dst_info
->bmiHeader
.biClrUsed
== 1 << dst_info
->bmiHeader
.biBitCount
)
565 dst_info
->bmiHeader
.biClrUsed
= 0;
570 FIXME( "Unknown brush style %x\n", logbrush
.lbStyle
);
574 r
= metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) );
575 HeapFree(GetProcessHeap(), 0, mr
);
578 return metadc_add_handle( metadc
, brush
);
581 static INT16
metadc_create_region( struct metadc
*metadc
, HRGN hrgn
)
586 RECT
*cur_rect
, *end_rect
;
587 WORD bands
= 0, max_bounds
= 0;
588 WORD
*param
, *start_band
;
591 if (!(len
= NtGdiGetRegionData( hrgn
, 0, NULL
))) return -1;
592 if (!(rgndata
= HeapAlloc( GetProcessHeap(), 0, len
)))
594 WARN( "Can't alloc rgndata buffer\n" );
597 NtGdiGetRegionData( hrgn
, len
, rgndata
);
599 /* Overestimate of length:
600 * Assume every rect is a separate band -> 6 WORDs per rect,
601 * see MF_Play_MetaCreateRegion for format details.
603 len
= sizeof(METARECORD
) + 20 + rgndata
->rdh
.nCount
* 12;
604 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
)))
606 WARN( "Can't alloc METARECORD buffer\n" );
607 HeapFree( GetProcessHeap(), 0, rgndata
);
611 param
= mr
->rdParm
+ 11;
614 end_rect
= (RECT
*)rgndata
->Buffer
+ rgndata
->rdh
.nCount
;
615 for (cur_rect
= (RECT
*)rgndata
->Buffer
; cur_rect
< end_rect
; cur_rect
++)
617 if (start_band
&& cur_rect
->top
== start_band
[1])
619 *param
++ = cur_rect
->left
;
620 *param
++ = cur_rect
->right
;
626 *start_band
= param
- start_band
- 3;
627 *param
++ = *start_band
;
628 if (*start_band
> max_bounds
)
629 max_bounds
= *start_band
;
632 start_band
= param
++;
633 *param
++ = cur_rect
->top
;
634 *param
++ = cur_rect
->bottom
;
635 *param
++ = cur_rect
->left
;
636 *param
++ = cur_rect
->right
;
642 *start_band
= param
- start_band
- 3;
643 *param
++ = *start_band
;
644 if (*start_band
> max_bounds
)
645 max_bounds
= *start_band
;
651 mr
->rdParm
[2] = 0x2f6;
653 mr
->rdParm
[4] = (param
- &mr
->rdFunction
) * sizeof(WORD
);
654 mr
->rdParm
[5] = bands
;
655 mr
->rdParm
[6] = max_bounds
;
656 mr
->rdParm
[7] = rgndata
->rdh
.rcBound
.left
;
657 mr
->rdParm
[8] = rgndata
->rdh
.rcBound
.top
;
658 mr
->rdParm
[9] = rgndata
->rdh
.rcBound
.right
;
659 mr
->rdParm
[10] = rgndata
->rdh
.rcBound
.bottom
;
660 mr
->rdFunction
= META_CREATEREGION
;
661 mr
->rdSize
= param
- (WORD
*)mr
;
662 ret
= metadc_write_record( metadc
, mr
, mr
->rdSize
* 2 );
663 HeapFree( GetProcessHeap(), 0, mr
);
664 HeapFree( GetProcessHeap(), 0, rgndata
);
667 WARN("MFDRV_WriteRecord failed\n");
670 return metadc_add_handle( metadc
, hrgn
);
673 BOOL
METADC_PaintRgn( HDC hdc
, HRGN hrgn
)
675 struct metadc
*metadc
;
677 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
678 index
= metadc_create_region( metadc
, hrgn
);
679 if(index
== -1) return FALSE
;
680 return metadc_param1( hdc
, META_PAINTREGION
, index
);
683 BOOL
METADC_InvertRgn( HDC hdc
, HRGN hrgn
)
685 struct metadc
*metadc
;
687 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
688 index
= metadc_create_region( metadc
, hrgn
);
689 if (index
== -1) return FALSE
;
690 return metadc_param1( hdc
, META_INVERTREGION
, index
);
693 BOOL
METADC_FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
695 struct metadc
*metadc
;
698 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
700 rgn
= metadc_create_region( metadc
, hrgn
);
701 if (rgn
== -1) return FALSE
;
702 brush
= metadc_create_brush( metadc
, hbrush
);
703 if (!brush
) return FALSE
;
704 return metadc_param2( hdc
, META_FILLREGION
, rgn
, brush
);
707 BOOL
METADC_FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, INT x
, INT y
)
709 struct metadc
*metadc
;
712 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
713 rgn
= metadc_create_region( metadc
, hrgn
);
714 if (rgn
== -1) return FALSE
;
715 brush
= metadc_create_brush( metadc
, hbrush
);
716 if (!brush
) return FALSE
;
717 return metadc_param4( hdc
, META_FRAMEREGION
, rgn
, brush
, x
, y
);
720 BOOL
METADC_PatBlt( HDC hdc
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
722 return metadc_param6( hdc
, META_PATBLT
, left
, top
, width
, height
,
723 HIWORD(rop
), LOWORD(rop
) );
726 static BOOL
metadc_stretchblt( HDC hdc
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
727 HDC hdc_src
, INT x_src
, INT y_src
, INT width_src
, INT height_src
,
728 DWORD rop
, WORD type
)
730 BITMAPINFO src_info
= {{ sizeof( src_info
.bmiHeader
) }};
731 UINT bmi_size
, size
, bpp
;
732 int i
= 0, bitmap_offset
;
738 if (!(bitmap
= GetCurrentObject( hdc_src
, OBJ_BITMAP
))) return FALSE
;
739 if (!GetDIBits( hdc_src
, bitmap
, 0, INT_MAX
, NULL
, &src_info
, DIB_RGB_COLORS
)) return FALSE
;
741 bpp
= src_info
.bmiHeader
.biBitCount
;
743 bmi_size
= sizeof(BITMAPINFOHEADER
) + (1 << bpp
) * sizeof(RGBQUAD
);
744 else if (bpp
== 16 || bpp
== 32)
745 bmi_size
= sizeof(BITMAPINFOHEADER
) + 3 * sizeof(RGBQUAD
);
747 bmi_size
= sizeof(BITMAPINFOHEADER
);
749 bitmap_offset
= type
== META_DIBBITBLT
? 8 : 10;
750 size
= FIELD_OFFSET( METARECORD
, rdParm
[bitmap_offset
] ) + bmi_size
+
751 src_info
.bmiHeader
.biSizeImage
;
752 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
753 mr
->rdFunction
= type
;
754 bmi
= (BITMAPINFO
*)&mr
->rdParm
[bitmap_offset
];
755 bmi
->bmiHeader
= src_info
.bmiHeader
;
756 TRACE( "size = %u rop=%lx\n", size
, rop
);
758 ret
= GetDIBits( hdc_src
, bitmap
, 0, src_info
.bmiHeader
.biHeight
, (BYTE
*)bmi
+ bmi_size
,
759 bmi
, DIB_RGB_COLORS
);
762 mr
->rdSize
= size
/ sizeof(WORD
);
763 mr
->rdParm
[i
++] = LOWORD(rop
);
764 mr
->rdParm
[i
++] = HIWORD(rop
);
765 if (bitmap_offset
> 8)
767 mr
->rdParm
[i
++] = height_src
;
768 mr
->rdParm
[i
++] = width_src
;
770 mr
->rdParm
[i
++] = y_src
;
771 mr
->rdParm
[i
++] = x_src
;
772 mr
->rdParm
[i
++] = height_dst
;
773 mr
->rdParm
[i
++] = width_dst
;
774 mr
->rdParm
[i
++] = y_dst
;
775 mr
->rdParm
[i
++] = x_dst
;
776 ret
= metadc_record( hdc
, mr
, size
);
779 HeapFree( GetProcessHeap(), 0, mr
);
783 BOOL
METADC_BitBlt( HDC hdc
, INT x_dst
, INT y_dst
, INT width
, INT height
,
784 HDC hdc_src
, INT x_src
, INT y_src
, DWORD rop
)
786 return metadc_stretchblt( hdc
, x_dst
, y_dst
, width
, height
,
787 hdc_src
, x_src
, y_src
, width
, height
, rop
, META_DIBBITBLT
);
790 BOOL
METADC_StretchBlt( HDC hdc_dst
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
791 HDC hdc_src
, INT x_src
, INT y_src
, INT width_src
, INT height_src
,
794 return metadc_stretchblt( hdc_dst
, x_dst
, y_dst
, width_dst
, height_dst
,
795 hdc_src
, x_src
, y_src
, width_src
, height_src
, rop
, META_DIBSTRETCHBLT
);
798 INT
METADC_StretchDIBits( HDC hdc
, INT x_dst
, INT y_dst
, INT width_dst
,
799 INT height_dst
, INT x_src
, INT y_src
, INT width_src
,
800 INT height_src
, const void *bits
,
801 const BITMAPINFO
*info
, UINT usage
, DWORD rop
)
803 DWORD infosize
= get_dib_info_size( info
, usage
);
804 DWORD len
= sizeof(METARECORD
) + 10 * sizeof(WORD
) + infosize
+ info
->bmiHeader
.biSizeImage
;
807 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, len
))) return 0;
809 mr
->rdSize
= len
/ sizeof(WORD
);
810 mr
->rdFunction
= META_STRETCHDIB
;
811 mr
->rdParm
[0] = LOWORD(rop
);
812 mr
->rdParm
[1] = HIWORD(rop
);
813 mr
->rdParm
[2] = usage
;
814 mr
->rdParm
[3] = height_src
;
815 mr
->rdParm
[4] = width_src
;
816 mr
->rdParm
[5] = y_src
;
817 mr
->rdParm
[6] = x_src
;
818 mr
->rdParm
[7] = height_dst
;
819 mr
->rdParm
[8] = width_dst
;
820 mr
->rdParm
[9] = y_dst
;
821 mr
->rdParm
[10] = x_dst
;
822 memcpy( mr
->rdParm
+ 11, info
, infosize
);
823 memcpy( mr
->rdParm
+ 11 + infosize
/ 2, bits
, info
->bmiHeader
.biSizeImage
);
824 metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
825 HeapFree( GetProcessHeap(), 0, mr
);
829 INT
METADC_SetDIBitsToDevice( HDC hdc
, INT x_dst
, INT y_dst
, DWORD width
, DWORD height
,
830 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
831 const void *bits
, const BITMAPINFO
*info
, UINT coloruse
)
834 DWORD infosize
= get_dib_info_size(info
, coloruse
);
835 DWORD len
= sizeof(METARECORD
) + 8 * sizeof(WORD
) + infosize
+ info
->bmiHeader
.biSizeImage
;
838 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, len
))) return 0;
840 mr
->rdSize
= len
/ sizeof(WORD
);
841 mr
->rdFunction
= META_SETDIBTODEV
;
842 mr
->rdParm
[0] = coloruse
;
843 mr
->rdParm
[1] = lines
;
844 mr
->rdParm
[2] = startscan
;
845 mr
->rdParm
[3] = y_src
;
846 mr
->rdParm
[4] = x_src
;
847 mr
->rdParm
[5] = height
;
848 mr
->rdParm
[6] = width
;
849 mr
->rdParm
[7] = y_dst
;
850 mr
->rdParm
[8] = x_dst
;
851 memcpy( mr
->rdParm
+ 9, info
, infosize
);
852 memcpy( mr
->rdParm
+ 9 + infosize
/ sizeof(WORD
), bits
, info
->bmiHeader
.biSizeImage
);
853 metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
854 HeapFree( GetProcessHeap(), 0, mr
);
858 static BOOL
metadc_text( HDC hdc
, short x
, short y
, UINT16 flags
, const RECT16
*rect
,
859 const char *str
, short count
, const INT16
*dx
)
864 BOOL isrect
= flags
& (ETO_CLIPPED
| ETO_OPAQUE
);
866 len
= sizeof(METARECORD
) + (((count
+ 1) >> 1) * 2) + 2 * sizeof(short)
868 if (isrect
) len
+= sizeof(RECT16
);
869 if (dx
) len
+= count
* sizeof(INT16
);
870 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
))) return FALSE
;
872 mr
->rdSize
= len
/ sizeof(WORD
);
873 mr
->rdFunction
= META_EXTTEXTOUT
;
876 mr
->rdParm
[2] = count
;
877 mr
->rdParm
[3] = flags
;
878 if (isrect
) memcpy( mr
->rdParm
+ 4, rect
, sizeof(RECT16
) );
879 memcpy( mr
->rdParm
+ (isrect
? 8 : 4), str
, count
);
881 memcpy( mr
->rdParm
+ (isrect
? 8 : 4) + ((count
+ 1) >> 1), dx
, count
* sizeof(INT16
) );
882 ret
= metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
883 HeapFree( GetProcessHeap(), 0, mr
);
887 BOOL
METADC_ExtTextOut( HDC hdc
, INT x
, INT y
, UINT flags
, const RECT
*lprect
,
888 const WCHAR
*str
, UINT count
, const INT
*dx
)
891 LPINT16 lpdx16
= NULL
;
897 int charset
= GetTextCharset( hdc
);
900 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
909 case DEFAULT_CHARSET
:
920 /* FIXME: These have no place here, but because x11drv
921 enumerates fonts with these (made up) charsets some apps
922 might use them and then the FIXME below would become
923 annoying. Now we could pick the intended codepage for
924 each of these, but since it's broken anyway we'll just
925 use CP_ACP and hope it'll go away...
931 FIXME("Can't find codepage for charset %d\n", charset
);
937 TRACE( "cp = %d\n", cp
);
938 len
= WideCharToMultiByte( cp
, 0, str
, count
, NULL
, 0, NULL
, NULL
);
939 ascii
= HeapAlloc( GetProcessHeap(), 0, len
);
940 WideCharToMultiByte( cp
, 0, str
, count
, ascii
, len
, NULL
, NULL
);
941 TRACE( "mapped %s -> %s\n", debugstr_wn(str
, count
), debugstr_an(ascii
, len
) );
946 rect16
.left
= lprect
->left
;
947 rect16
.top
= lprect
->top
;
948 rect16
.right
= lprect
->right
;
949 rect16
.bottom
= lprect
->bottom
;
954 lpdx16
= HeapAlloc( GetProcessHeap(), 0, sizeof(INT16
) * len
);
955 for (i
= j
= 0; i
< len
; )
956 if (IsDBCSLeadByteEx( cp
, ascii
[i
] ))
958 lpdx16
[i
++] = dx
[j
++];
962 lpdx16
[i
++] = dx
[j
++];
965 ret
= metadc_text( hdc
, x
, y
, flags
, lprect
? &rect16
: NULL
, ascii
, len
, lpdx16
);
966 HeapFree( GetProcessHeap(), 0, ascii
);
967 HeapFree( GetProcessHeap(), 0, lpdx16
);
971 BOOL
METADC_ExtSelectClipRgn( HDC hdc
, HRGN hrgn
, INT mode
)
973 struct metadc
*metadc
;
977 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
978 if (mode
!= RGN_COPY
) return ERROR
;
979 if (!hrgn
) return NULLREGION
;
980 rgn
= metadc_create_region( metadc
, hrgn
);
981 if(rgn
== -1) return ERROR
;
982 ret
= metadc_param1( hdc
, META_SELECTOBJECT
, rgn
) ? NULLREGION
: ERROR
;
983 metadc_param1( hdc
, META_DELETEOBJECT
, rgn
);
984 metadc_remove_handle( metadc
, rgn
);
988 static INT16
metadc_find_object( struct metadc
*metadc
, HGDIOBJ obj
)
992 for (index
= 0; index
< metadc
->handles_size
; index
++)
993 if (metadc
->handles
[index
] == obj
) return index
;
998 static void METADC_DeleteObject( HDC hdc
, HGDIOBJ obj
)
1000 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1004 if ((index
= metadc_find_object( metadc
, obj
)) < 0) return;
1005 if (obj
== metadc
->pen
|| obj
== metadc
->brush
|| obj
== metadc
->font
)
1007 WARN( "deleting selected object %p\n", obj
);
1011 mr
.rdSize
= sizeof(mr
) / sizeof(WORD
);
1012 mr
.rdFunction
= META_DELETEOBJECT
;
1013 mr
.rdParm
[0] = index
;
1015 metadc_write_record( metadc
, &mr
, mr
.rdSize
* sizeof(WORD
) );
1017 metadc
->handles
[index
] = 0;
1018 metadc
->cur_handles
--;
1021 static BOOL
metadc_select_object( HDC hdc
, INT16 index
)
1025 mr
.rdSize
= sizeof mr
/ 2;
1026 mr
.rdFunction
= META_SELECTOBJECT
;
1027 mr
.rdParm
[0] = index
;
1028 return metadc_record( hdc
, &mr
, mr
.rdSize
* sizeof(WORD
) );
1031 static HBRUSH
METADC_SelectBrush( HDC hdc
, HBRUSH hbrush
)
1033 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1037 index
= metadc_find_object( metadc
, hbrush
);
1040 index
= metadc_create_brush( metadc
, hbrush
);
1043 GDI_hdc_using_object( hbrush
, hdc
, METADC_DeleteObject
);
1045 if (!metadc_select_object( hdc
, index
)) return 0;
1046 ret
= metadc
->brush
;
1047 metadc
->brush
= hbrush
;
1051 static UINT16
metadc_create_font( struct metadc
*metadc
, HFONT font
, LOGFONTW
*logfont
)
1053 char buffer
[sizeof(METARECORD
) - 2 + sizeof(LOGFONT16
)];
1054 METARECORD
*mr
= (METARECORD
*)&buffer
;
1058 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(LOGFONT16
) - 2) / 2;
1059 mr
->rdFunction
= META_CREATEFONTINDIRECT
;
1060 font16
= (LOGFONT16
*)&mr
->rdParm
;
1062 font16
->lfHeight
= logfont
->lfHeight
;
1063 font16
->lfWidth
= logfont
->lfWidth
;
1064 font16
->lfEscapement
= logfont
->lfEscapement
;
1065 font16
->lfOrientation
= logfont
->lfOrientation
;
1066 font16
->lfWeight
= logfont
->lfWeight
;
1067 font16
->lfItalic
= logfont
->lfItalic
;
1068 font16
->lfUnderline
= logfont
->lfUnderline
;
1069 font16
->lfStrikeOut
= logfont
->lfStrikeOut
;
1070 font16
->lfCharSet
= logfont
->lfCharSet
;
1071 font16
->lfOutPrecision
= logfont
->lfOutPrecision
;
1072 font16
->lfClipPrecision
= logfont
->lfClipPrecision
;
1073 font16
->lfQuality
= logfont
->lfQuality
;
1074 font16
->lfPitchAndFamily
= logfont
->lfPitchAndFamily
;
1075 written
= WideCharToMultiByte( CP_ACP
, 0, logfont
->lfFaceName
, -1, font16
->lfFaceName
,
1076 LF_FACESIZE
- 1, NULL
, NULL
);
1077 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
1078 memset( font16
->lfFaceName
+ written
, 0, LF_FACESIZE
- written
);
1080 if (!metadc_write_record( metadc
, mr
, mr
->rdSize
* 2 ))
1082 return metadc_add_handle( metadc
, font
);
1085 static HFONT
METADC_SelectFont( HDC hdc
, HFONT hfont
)
1087 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1092 index
= metadc_find_object( metadc
, hfont
);
1095 if (!GetObjectW( hfont
, sizeof(font
), &font
))
1097 index
= metadc_create_font( metadc
, hfont
, &font
);
1100 GDI_hdc_using_object( hfont
, hdc
, METADC_DeleteObject
);
1102 if (!metadc_select_object( hdc
, index
)) return 0;
1104 metadc
->font
= hfont
;
1108 static UINT16
metadc_create_pen( struct metadc
*metadc
, HPEN pen
, LOGPEN16
*logpen
)
1110 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[sizeof(*logpen
) / sizeof(WORD
)])];
1111 METARECORD
*mr
= (METARECORD
*)&buffer
;
1113 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
1114 mr
->rdFunction
= META_CREATEPENINDIRECT
;
1115 memcpy( mr
->rdParm
, logpen
, sizeof(*logpen
) );
1116 if (!metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) )) return 0;
1117 return metadc_add_handle( metadc
, pen
);
1120 static HPEN
METADC_SelectPen( HDC hdc
, HPEN hpen
)
1122 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1127 index
= metadc_find_object( metadc
, hpen
);
1130 /* must be an extended pen */
1131 INT size
= GetObjectW( hpen
, 0, NULL
);
1133 if (!size
) return 0;
1135 if (size
== sizeof(LOGPEN
))
1139 GetObjectW( hpen
, sizeof(pen
), &pen
);
1140 logpen
.lopnStyle
= pen
.lopnStyle
;
1141 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
1142 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
1143 logpen
.lopnColor
= pen
.lopnColor
;
1145 else /* must be an extended pen */
1147 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
1149 GetObjectW( hpen
, size
, elp
);
1150 /* FIXME: add support for user style pens */
1151 logpen
.lopnStyle
= elp
->elpPenStyle
;
1152 logpen
.lopnWidth
.x
= elp
->elpWidth
;
1153 logpen
.lopnWidth
.y
= 0;
1154 logpen
.lopnColor
= elp
->elpColor
;
1156 HeapFree( GetProcessHeap(), 0, elp
);
1159 index
= metadc_create_pen( metadc
, hpen
, &logpen
);
1162 GDI_hdc_using_object( hpen
, hdc
, METADC_DeleteObject
);
1165 if (!metadc_select_object( hdc
, index
)) return 0;
1171 static BOOL
metadc_create_palette( struct metadc
*metadc
, HPALETTE palette
,
1172 LOGPALETTE
*log_palette
, int sizeofPalette
)
1178 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
1179 if (!mr
) return FALSE
;
1180 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
1181 mr
->rdFunction
= META_CREATEPALETTE
;
1182 memcpy(&(mr
->rdParm
), log_palette
, sizeofPalette
);
1183 if (!metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) ))
1185 HeapFree(GetProcessHeap(), 0, mr
);
1189 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
1190 mr
->rdFunction
= META_SELECTPALETTE
;
1192 if ((index
= metadc_add_handle( metadc
, palette
)) == -1) ret
= FALSE
;
1195 mr
->rdParm
[0] = index
;
1196 ret
= metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) );
1198 HeapFree( GetProcessHeap(), 0, mr
);
1202 BOOL
METADC_SelectPalette( HDC hdc
, HPALETTE palette
)
1204 struct metadc
*metadc
;
1205 PLOGPALETTE log_palette
;
1210 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
1211 GetObjectA( palette
, sizeof(WORD
), &count
);
1212 if (!count
) return 0;
1214 size
= sizeof(LOGPALETTE
) + (count
- 1) * sizeof(PALETTEENTRY
);
1215 log_palette
= HeapAlloc( GetProcessHeap(), 0, size
);
1216 if (!log_palette
) return 0;
1218 log_palette
->palVersion
= 0x300;
1219 log_palette
->palNumEntries
= count
;
1221 GetPaletteEntries( palette
, 0, count
, log_palette
->palPalEntry
);
1223 ret
= metadc_create_palette( metadc
, palette
, log_palette
, size
);
1225 HeapFree( GetProcessHeap(), 0, log_palette
);
1229 BOOL
METADC_RealizePalette( HDC hdc
)
1231 return metadc_param0( hdc
, META_REALIZEPALETTE
);
1234 HGDIOBJ
METADC_SelectObject( HDC hdc
, HGDIOBJ obj
)
1236 switch (gdi_handle_type( obj
))
1238 case NTGDI_OBJ_BRUSH
:
1239 return METADC_SelectBrush( hdc
, obj
);
1240 case NTGDI_OBJ_FONT
:
1241 return METADC_SelectFont( hdc
, obj
);
1243 case NTGDI_OBJ_EXTPEN
:
1244 return METADC_SelectPen( hdc
, obj
);
1246 SetLastError( ERROR_INVALID_FUNCTION
);
1251 BOOL
METADC_ExtEscape( HDC hdc
, INT escape
, INT input_size
, const void *input
,
1252 INT output_size
, void *output
)
1258 if (output_size
) return FALSE
; /* escapes that require output cannot work in metafiles */
1260 len
= sizeof(*mr
) + sizeof(WORD
) + ((input_size
+ 1) & ~1);
1261 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
))) return FALSE
;
1262 mr
->rdSize
= len
/ sizeof(WORD
);
1263 mr
->rdFunction
= META_ESCAPE
;
1264 mr
->rdParm
[0] = escape
;
1265 mr
->rdParm
[1] = input_size
;
1266 memcpy( &mr
->rdParm
[2], input
, input_size
);
1267 ret
= metadc_record( hdc
, mr
, len
);
1268 HeapFree(GetProcessHeap(), 0, mr
);
1272 INT
METADC_GetDeviceCaps( HDC hdc
, INT cap
)
1274 if (!get_metadc_ptr( hdc
)) return 0;
1283 TRACE(" unsupported capability %d, will return 0\n", cap
);
1288 static void metadc_free( struct metadc
*metadc
)
1292 CloseHandle( metadc
->hFile
);
1293 HeapFree( GetProcessHeap(), 0, metadc
->mh
);
1294 for(index
= 0; index
< metadc
->handles_size
; index
++)
1295 if(metadc
->handles
[index
])
1296 GDI_hdc_not_using_object( metadc
->handles
[index
], metadc
->hdc
);
1297 HeapFree( GetProcessHeap(), 0, metadc
->handles
);
1298 HeapFree( GetProcessHeap(), 0, metadc
);
1301 BOOL
METADC_DeleteDC( HDC hdc
)
1303 struct metadc
*metadc
;
1305 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
1306 if (!NtGdiDeleteClientObj( hdc
)) return FALSE
;
1307 metadc_free( metadc
);
1311 /**********************************************************************
1312 * CreateMetaFileW (GDI32.@)
1314 * Create a new DC and associate it with a metafile. Pass a filename
1315 * to create a disk-based metafile, NULL to create a memory metafile.
1317 HDC WINAPI
CreateMetaFileW( const WCHAR
*filename
)
1319 struct metadc
*metadc
;
1322 TRACE( "%s\n", debugstr_w(filename
) );
1324 if (!(hdc
= NtGdiCreateClientObj( NTGDI_OBJ_METADC
))) return NULL
;
1326 metadc
= HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc
) );
1329 NtGdiDeleteClientObj( hdc
);
1332 if (!(metadc
->mh
= HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc
->mh
) )))
1334 HeapFree( GetProcessHeap(), 0, metadc
);
1335 NtGdiDeleteClientObj( hdc
);
1340 set_gdi_client_ptr( hdc
, metadc
);
1342 metadc
->handles
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1343 HANDLE_LIST_INC
* sizeof(metadc
->handles
[0]) );
1344 metadc
->handles_size
= HANDLE_LIST_INC
;
1345 metadc
->cur_handles
= 0;
1349 metadc
->mh
->mtHeaderSize
= sizeof(METAHEADER
) / sizeof(WORD
);
1350 metadc
->mh
->mtVersion
= 0x0300;
1351 metadc
->mh
->mtSize
= metadc
->mh
->mtHeaderSize
;
1352 metadc
->mh
->mtNoObjects
= 0;
1353 metadc
->mh
->mtMaxRecord
= 0;
1354 metadc
->mh
->mtNoParameters
= 0;
1355 metadc
->mh
->mtType
= METAFILE_MEMORY
;
1357 metadc
->pen
= GetStockObject( BLACK_PEN
);
1358 metadc
->brush
= GetStockObject( WHITE_BRUSH
);
1359 metadc
->font
= GetStockObject( DEVICE_DEFAULT_FONT
);
1361 if (filename
) /* disk based metafile */
1363 HANDLE file
= CreateFileW( filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1364 if (file
== INVALID_HANDLE_VALUE
)
1366 HeapFree( GetProcessHeap(), 0, metadc
);
1367 NtGdiDeleteClientObj( hdc
);
1370 metadc
->hFile
= file
;
1373 TRACE( "returning %p\n", hdc
);
1377 /**********************************************************************
1378 * CreateMetaFileA (GDI32.@)
1380 HDC WINAPI
CreateMetaFileA( const char *filename
)
1386 if (!filename
) return CreateMetaFileW( NULL
);
1388 len
= MultiByteToWideChar( CP_ACP
, 0, filename
, -1, NULL
, 0 );
1389 filenameW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
1390 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, filenameW
, len
);
1392 hdc
= CreateMetaFileW( filenameW
);
1394 HeapFree( GetProcessHeap(), 0, filenameW
);
1398 /******************************************************************
1399 * CloseMetaFile (GDI32.@)
1401 * Stop recording graphics operations in metafile associated with
1402 * hdc and retrieve metafile.
1404 HMETAFILE WINAPI
CloseMetaFile( HDC hdc
)
1406 struct metadc
*metadc
;
1407 DWORD bytes_written
;
1410 TRACE( "(%p)\n", hdc
);
1412 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
1414 /* Construct the end of metafile record - this is documented
1415 * in SDK Knowledgebase Q99334.
1417 if (!metadc_param0( hdc
, META_EOF
)) return FALSE
;
1418 if (!NtGdiDeleteClientObj( hdc
)) return FALSE
;
1420 if (metadc
->hFile
&& !WriteFile( metadc
->hFile
, metadc
->mh
, metadc
->mh
->mtSize
* sizeof(WORD
),
1421 &bytes_written
, NULL
))
1423 metadc_free( metadc
);
1427 /* Now allocate a global handle for the metafile */
1428 hmf
= MF_Create_HMETAFILE( metadc
->mh
);
1429 if (hmf
) metadc
->mh
= NULL
; /* So it won't be deleted */
1430 metadc_free( metadc
);