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 (!__wine_get_brush_bitmap_info( brush
, src_info
, NULL
, &usage
)) goto done
;
552 info_size
= get_dib_info_size( src_info
, usage
);
553 size
= FIELD_OFFSET( METARECORD
, rdParm
[2] ) +
554 info_size
+ src_info
->bmiHeader
.biSizeImage
;
556 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
557 mr
->rdFunction
= META_DIBCREATEPATTERNBRUSH
;
558 mr
->rdSize
= size
/ sizeof(WORD
);
559 mr
->rdParm
[0] = logbrush
.lbStyle
;
560 mr
->rdParm
[1] = usage
;
561 dst_info
= (BITMAPINFO
*)(mr
->rdParm
+ 2);
562 __wine_get_brush_bitmap_info( brush
, dst_info
, (char *)dst_info
+ info_size
, NULL
);
563 if (dst_info
->bmiHeader
.biClrUsed
== 1 << dst_info
->bmiHeader
.biBitCount
)
564 dst_info
->bmiHeader
.biClrUsed
= 0;
569 FIXME( "Unknown brush style %x\n", logbrush
.lbStyle
);
573 r
= metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) );
574 HeapFree(GetProcessHeap(), 0, mr
);
577 return metadc_add_handle( metadc
, brush
);
580 static INT16
metadc_create_region( struct metadc
*metadc
, HRGN hrgn
)
585 RECT
*cur_rect
, *end_rect
;
586 WORD bands
= 0, max_bounds
= 0;
587 WORD
*param
, *start_band
;
590 if (!(len
= NtGdiGetRegionData( hrgn
, 0, NULL
))) return -1;
591 if (!(rgndata
= HeapAlloc( GetProcessHeap(), 0, len
)))
593 WARN( "Can't alloc rgndata buffer\n" );
596 NtGdiGetRegionData( hrgn
, len
, rgndata
);
598 /* Overestimate of length:
599 * Assume every rect is a separate band -> 6 WORDs per rect,
600 * see MF_Play_MetaCreateRegion for format details.
602 len
= sizeof(METARECORD
) + 20 + rgndata
->rdh
.nCount
* 12;
603 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
)))
605 WARN( "Can't alloc METARECORD buffer\n" );
606 HeapFree( GetProcessHeap(), 0, rgndata
);
610 param
= mr
->rdParm
+ 11;
613 end_rect
= (RECT
*)rgndata
->Buffer
+ rgndata
->rdh
.nCount
;
614 for (cur_rect
= (RECT
*)rgndata
->Buffer
; cur_rect
< end_rect
; cur_rect
++)
616 if (start_band
&& cur_rect
->top
== start_band
[1])
618 *param
++ = cur_rect
->left
;
619 *param
++ = cur_rect
->right
;
625 *start_band
= param
- start_band
- 3;
626 *param
++ = *start_band
;
627 if (*start_band
> max_bounds
)
628 max_bounds
= *start_band
;
631 start_band
= param
++;
632 *param
++ = cur_rect
->top
;
633 *param
++ = cur_rect
->bottom
;
634 *param
++ = cur_rect
->left
;
635 *param
++ = cur_rect
->right
;
641 *start_band
= param
- start_band
- 3;
642 *param
++ = *start_band
;
643 if (*start_band
> max_bounds
)
644 max_bounds
= *start_band
;
650 mr
->rdParm
[2] = 0x2f6;
652 mr
->rdParm
[4] = (param
- &mr
->rdFunction
) * sizeof(WORD
);
653 mr
->rdParm
[5] = bands
;
654 mr
->rdParm
[6] = max_bounds
;
655 mr
->rdParm
[7] = rgndata
->rdh
.rcBound
.left
;
656 mr
->rdParm
[8] = rgndata
->rdh
.rcBound
.top
;
657 mr
->rdParm
[9] = rgndata
->rdh
.rcBound
.right
;
658 mr
->rdParm
[10] = rgndata
->rdh
.rcBound
.bottom
;
659 mr
->rdFunction
= META_CREATEREGION
;
660 mr
->rdSize
= param
- (WORD
*)mr
;
661 ret
= metadc_write_record( metadc
, mr
, mr
->rdSize
* 2 );
662 HeapFree( GetProcessHeap(), 0, mr
);
663 HeapFree( GetProcessHeap(), 0, rgndata
);
666 WARN("MFDRV_WriteRecord failed\n");
669 return metadc_add_handle( metadc
, hrgn
);
672 BOOL
METADC_PaintRgn( HDC hdc
, HRGN hrgn
)
674 struct metadc
*metadc
;
676 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
677 index
= metadc_create_region( metadc
, hrgn
);
678 if(index
== -1) return FALSE
;
679 return metadc_param1( hdc
, META_PAINTREGION
, index
);
682 BOOL
METADC_InvertRgn( HDC hdc
, HRGN hrgn
)
684 struct metadc
*metadc
;
686 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
687 index
= metadc_create_region( metadc
, hrgn
);
688 if (index
== -1) return FALSE
;
689 return metadc_param1( hdc
, META_INVERTREGION
, index
);
692 BOOL
METADC_FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
694 struct metadc
*metadc
;
697 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
699 rgn
= metadc_create_region( metadc
, hrgn
);
700 if (rgn
== -1) return FALSE
;
701 brush
= metadc_create_brush( metadc
, hbrush
);
702 if (!brush
) return FALSE
;
703 return metadc_param2( hdc
, META_FILLREGION
, rgn
, brush
);
706 BOOL
METADC_FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, INT x
, INT y
)
708 struct metadc
*metadc
;
711 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
712 rgn
= metadc_create_region( metadc
, hrgn
);
713 if (rgn
== -1) return FALSE
;
714 brush
= metadc_create_brush( metadc
, hbrush
);
715 if (!brush
) return FALSE
;
716 return metadc_param4( hdc
, META_FRAMEREGION
, rgn
, brush
, x
, y
);
719 BOOL
METADC_PatBlt( HDC hdc
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
721 return metadc_param6( hdc
, META_PATBLT
, left
, top
, width
, height
,
722 HIWORD(rop
), LOWORD(rop
) );
725 static BOOL
metadc_stretchblt( HDC hdc
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
726 HDC hdc_src
, INT x_src
, INT y_src
, INT width_src
, INT height_src
,
727 DWORD rop
, WORD type
)
729 BITMAPINFO src_info
= {{ sizeof( src_info
.bmiHeader
) }};
730 UINT bmi_size
, size
, bpp
;
731 int i
= 0, bitmap_offset
;
737 if (!(bitmap
= GetCurrentObject( hdc_src
, OBJ_BITMAP
))) return FALSE
;
738 if (!GetDIBits( hdc_src
, bitmap
, 0, INT_MAX
, NULL
, &src_info
, DIB_RGB_COLORS
)) return FALSE
;
740 bpp
= src_info
.bmiHeader
.biBitCount
;
742 bmi_size
= sizeof(BITMAPINFOHEADER
) + (1 << bpp
) * sizeof(RGBQUAD
);
743 else if (bpp
== 16 || bpp
== 32)
744 bmi_size
= sizeof(BITMAPINFOHEADER
) + 3 * sizeof(RGBQUAD
);
746 bmi_size
= sizeof(BITMAPINFOHEADER
);
748 bitmap_offset
= type
== META_DIBBITBLT
? 8 : 10;
749 size
= FIELD_OFFSET( METARECORD
, rdParm
[bitmap_offset
] ) + bmi_size
+
750 src_info
.bmiHeader
.biSizeImage
;
751 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
752 mr
->rdFunction
= type
;
753 bmi
= (BITMAPINFO
*)&mr
->rdParm
[bitmap_offset
];
754 bmi
->bmiHeader
= src_info
.bmiHeader
;
755 TRACE( "size = %u rop=%lx\n", size
, rop
);
757 ret
= GetDIBits( hdc_src
, bitmap
, 0, src_info
.bmiHeader
.biHeight
, (BYTE
*)bmi
+ bmi_size
,
758 bmi
, DIB_RGB_COLORS
);
761 mr
->rdSize
= size
/ sizeof(WORD
);
762 mr
->rdParm
[i
++] = LOWORD(rop
);
763 mr
->rdParm
[i
++] = HIWORD(rop
);
764 if (bitmap_offset
> 8)
766 mr
->rdParm
[i
++] = height_src
;
767 mr
->rdParm
[i
++] = width_src
;
769 mr
->rdParm
[i
++] = y_src
;
770 mr
->rdParm
[i
++] = x_src
;
771 mr
->rdParm
[i
++] = height_dst
;
772 mr
->rdParm
[i
++] = width_dst
;
773 mr
->rdParm
[i
++] = y_dst
;
774 mr
->rdParm
[i
++] = x_dst
;
775 ret
= metadc_record( hdc
, mr
, size
);
778 HeapFree( GetProcessHeap(), 0, mr
);
782 BOOL
METADC_BitBlt( HDC hdc
, INT x_dst
, INT y_dst
, INT width
, INT height
,
783 HDC hdc_src
, INT x_src
, INT y_src
, DWORD rop
)
785 return metadc_stretchblt( hdc
, x_dst
, y_dst
, width
, height
,
786 hdc_src
, x_src
, y_src
, width
, height
, rop
, META_DIBBITBLT
);
789 BOOL
METADC_StretchBlt( HDC hdc_dst
, INT x_dst
, INT y_dst
, INT width_dst
, INT height_dst
,
790 HDC hdc_src
, INT x_src
, INT y_src
, INT width_src
, INT height_src
,
793 return metadc_stretchblt( hdc_dst
, x_dst
, y_dst
, width_dst
, height_dst
,
794 hdc_src
, x_src
, y_src
, width_src
, height_src
, rop
, META_DIBSTRETCHBLT
);
797 INT
METADC_StretchDIBits( HDC hdc
, INT x_dst
, INT y_dst
, INT width_dst
,
798 INT height_dst
, INT x_src
, INT y_src
, INT width_src
,
799 INT height_src
, const void *bits
,
800 const BITMAPINFO
*info
, UINT usage
, DWORD rop
)
802 DWORD infosize
= get_dib_info_size( info
, usage
);
803 DWORD len
= sizeof(METARECORD
) + 10 * sizeof(WORD
) + infosize
+ info
->bmiHeader
.biSizeImage
;
806 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, len
))) return 0;
808 mr
->rdSize
= len
/ sizeof(WORD
);
809 mr
->rdFunction
= META_STRETCHDIB
;
810 mr
->rdParm
[0] = LOWORD(rop
);
811 mr
->rdParm
[1] = HIWORD(rop
);
812 mr
->rdParm
[2] = usage
;
813 mr
->rdParm
[3] = height_src
;
814 mr
->rdParm
[4] = width_src
;
815 mr
->rdParm
[5] = y_src
;
816 mr
->rdParm
[6] = x_src
;
817 mr
->rdParm
[7] = height_dst
;
818 mr
->rdParm
[8] = width_dst
;
819 mr
->rdParm
[9] = y_dst
;
820 mr
->rdParm
[10] = x_dst
;
821 memcpy( mr
->rdParm
+ 11, info
, infosize
);
822 memcpy( mr
->rdParm
+ 11 + infosize
/ 2, bits
, info
->bmiHeader
.biSizeImage
);
823 metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
824 HeapFree( GetProcessHeap(), 0, mr
);
828 INT
METADC_SetDIBitsToDevice( HDC hdc
, INT x_dst
, INT y_dst
, DWORD width
, DWORD height
,
829 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
830 const void *bits
, const BITMAPINFO
*info
, UINT coloruse
)
833 DWORD infosize
= get_dib_info_size(info
, coloruse
);
834 DWORD len
= sizeof(METARECORD
) + 8 * sizeof(WORD
) + infosize
+ info
->bmiHeader
.biSizeImage
;
837 if (!(mr
= HeapAlloc( GetProcessHeap(), 0, len
))) return 0;
839 mr
->rdSize
= len
/ sizeof(WORD
);
840 mr
->rdFunction
= META_SETDIBTODEV
;
841 mr
->rdParm
[0] = coloruse
;
842 mr
->rdParm
[1] = lines
;
843 mr
->rdParm
[2] = startscan
;
844 mr
->rdParm
[3] = y_src
;
845 mr
->rdParm
[4] = x_src
;
846 mr
->rdParm
[5] = height
;
847 mr
->rdParm
[6] = width
;
848 mr
->rdParm
[7] = y_dst
;
849 mr
->rdParm
[8] = x_dst
;
850 memcpy( mr
->rdParm
+ 9, info
, infosize
);
851 memcpy( mr
->rdParm
+ 9 + infosize
/ sizeof(WORD
), bits
, info
->bmiHeader
.biSizeImage
);
852 metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
853 HeapFree( GetProcessHeap(), 0, mr
);
857 static BOOL
metadc_text( HDC hdc
, short x
, short y
, UINT16 flags
, const RECT16
*rect
,
858 const char *str
, short count
, const INT16
*dx
)
863 BOOL isrect
= flags
& (ETO_CLIPPED
| ETO_OPAQUE
);
865 len
= sizeof(METARECORD
) + (((count
+ 1) >> 1) * 2) + 2 * sizeof(short)
867 if (isrect
) len
+= sizeof(RECT16
);
868 if (dx
) len
+= count
* sizeof(INT16
);
869 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
))) return FALSE
;
871 mr
->rdSize
= len
/ sizeof(WORD
);
872 mr
->rdFunction
= META_EXTTEXTOUT
;
875 mr
->rdParm
[2] = count
;
876 mr
->rdParm
[3] = flags
;
877 if (isrect
) memcpy( mr
->rdParm
+ 4, rect
, sizeof(RECT16
) );
878 memcpy( mr
->rdParm
+ (isrect
? 8 : 4), str
, count
);
880 memcpy( mr
->rdParm
+ (isrect
? 8 : 4) + ((count
+ 1) >> 1), dx
, count
* sizeof(INT16
) );
881 ret
= metadc_record( hdc
, mr
, mr
->rdSize
* sizeof(WORD
) );
882 HeapFree( GetProcessHeap(), 0, mr
);
886 BOOL
METADC_ExtTextOut( HDC hdc
, INT x
, INT y
, UINT flags
, const RECT
*lprect
,
887 const WCHAR
*str
, UINT count
, const INT
*dx
)
890 LPINT16 lpdx16
= NULL
;
896 int charset
= GetTextCharset( hdc
);
899 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
908 case DEFAULT_CHARSET
:
919 /* FIXME: These have no place here, but because x11drv
920 enumerates fonts with these (made up) charsets some apps
921 might use them and then the FIXME below would become
922 annoying. Now we could pick the intended codepage for
923 each of these, but since it's broken anyway we'll just
924 use CP_ACP and hope it'll go away...
930 FIXME("Can't find codepage for charset %d\n", charset
);
936 TRACE( "cp = %d\n", cp
);
937 len
= WideCharToMultiByte( cp
, 0, str
, count
, NULL
, 0, NULL
, NULL
);
938 ascii
= HeapAlloc( GetProcessHeap(), 0, len
);
939 WideCharToMultiByte( cp
, 0, str
, count
, ascii
, len
, NULL
, NULL
);
940 TRACE( "mapped %s -> %s\n", debugstr_wn(str
, count
), debugstr_an(ascii
, len
) );
945 rect16
.left
= lprect
->left
;
946 rect16
.top
= lprect
->top
;
947 rect16
.right
= lprect
->right
;
948 rect16
.bottom
= lprect
->bottom
;
953 lpdx16
= HeapAlloc( GetProcessHeap(), 0, sizeof(INT16
) * len
);
954 for (i
= j
= 0; i
< len
; )
955 if (IsDBCSLeadByteEx( cp
, ascii
[i
] ))
957 lpdx16
[i
++] = dx
[j
++];
961 lpdx16
[i
++] = dx
[j
++];
964 ret
= metadc_text( hdc
, x
, y
, flags
, lprect
? &rect16
: NULL
, ascii
, len
, lpdx16
);
965 HeapFree( GetProcessHeap(), 0, ascii
);
966 HeapFree( GetProcessHeap(), 0, lpdx16
);
970 BOOL
METADC_ExtSelectClipRgn( HDC hdc
, HRGN hrgn
, INT mode
)
972 struct metadc
*metadc
;
976 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
977 if (mode
!= RGN_COPY
) return ERROR
;
978 if (!hrgn
) return NULLREGION
;
979 rgn
= metadc_create_region( metadc
, hrgn
);
980 if(rgn
== -1) return ERROR
;
981 ret
= metadc_param1( hdc
, META_SELECTOBJECT
, rgn
) ? NULLREGION
: ERROR
;
982 metadc_param1( hdc
, META_DELETEOBJECT
, rgn
);
983 metadc_remove_handle( metadc
, rgn
);
987 static INT16
metadc_find_object( struct metadc
*metadc
, HGDIOBJ obj
)
991 for (index
= 0; index
< metadc
->handles_size
; index
++)
992 if (metadc
->handles
[index
] == obj
) return index
;
997 static void METADC_DeleteObject( HDC hdc
, HGDIOBJ obj
)
999 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1003 if ((index
= metadc_find_object( metadc
, obj
)) < 0) return;
1004 if (obj
== metadc
->pen
|| obj
== metadc
->brush
|| obj
== metadc
->font
)
1006 WARN( "deleting selected object %p\n", obj
);
1010 mr
.rdSize
= sizeof(mr
) / sizeof(WORD
);
1011 mr
.rdFunction
= META_DELETEOBJECT
;
1012 mr
.rdParm
[0] = index
;
1014 metadc_write_record( metadc
, &mr
, mr
.rdSize
* sizeof(WORD
) );
1016 metadc
->handles
[index
] = 0;
1017 metadc
->cur_handles
--;
1020 static BOOL
metadc_select_object( HDC hdc
, INT16 index
)
1024 mr
.rdSize
= sizeof mr
/ 2;
1025 mr
.rdFunction
= META_SELECTOBJECT
;
1026 mr
.rdParm
[0] = index
;
1027 return metadc_record( hdc
, &mr
, mr
.rdSize
* sizeof(WORD
) );
1030 static HBRUSH
METADC_SelectBrush( HDC hdc
, HBRUSH hbrush
)
1032 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1036 index
= metadc_find_object( metadc
, hbrush
);
1039 index
= metadc_create_brush( metadc
, hbrush
);
1042 GDI_hdc_using_object( hbrush
, hdc
, METADC_DeleteObject
);
1044 if (!metadc_select_object( hdc
, index
)) return 0;
1045 ret
= metadc
->brush
;
1046 metadc
->brush
= hbrush
;
1050 static UINT16
metadc_create_font( struct metadc
*metadc
, HFONT font
, LOGFONTW
*logfont
)
1052 char buffer
[sizeof(METARECORD
) - 2 + sizeof(LOGFONT16
)];
1053 METARECORD
*mr
= (METARECORD
*)&buffer
;
1057 mr
->rdSize
= (sizeof(METARECORD
) + sizeof(LOGFONT16
) - 2) / 2;
1058 mr
->rdFunction
= META_CREATEFONTINDIRECT
;
1059 font16
= (LOGFONT16
*)&mr
->rdParm
;
1061 font16
->lfHeight
= logfont
->lfHeight
;
1062 font16
->lfWidth
= logfont
->lfWidth
;
1063 font16
->lfEscapement
= logfont
->lfEscapement
;
1064 font16
->lfOrientation
= logfont
->lfOrientation
;
1065 font16
->lfWeight
= logfont
->lfWeight
;
1066 font16
->lfItalic
= logfont
->lfItalic
;
1067 font16
->lfUnderline
= logfont
->lfUnderline
;
1068 font16
->lfStrikeOut
= logfont
->lfStrikeOut
;
1069 font16
->lfCharSet
= logfont
->lfCharSet
;
1070 font16
->lfOutPrecision
= logfont
->lfOutPrecision
;
1071 font16
->lfClipPrecision
= logfont
->lfClipPrecision
;
1072 font16
->lfQuality
= logfont
->lfQuality
;
1073 font16
->lfPitchAndFamily
= logfont
->lfPitchAndFamily
;
1074 written
= WideCharToMultiByte( CP_ACP
, 0, logfont
->lfFaceName
, -1, font16
->lfFaceName
,
1075 LF_FACESIZE
- 1, NULL
, NULL
);
1076 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
1077 memset( font16
->lfFaceName
+ written
, 0, LF_FACESIZE
- written
);
1079 if (!metadc_write_record( metadc
, mr
, mr
->rdSize
* 2 ))
1081 return metadc_add_handle( metadc
, font
);
1084 static HFONT
METADC_SelectFont( HDC hdc
, HFONT hfont
)
1086 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1091 index
= metadc_find_object( metadc
, hfont
);
1094 if (!GetObjectW( hfont
, sizeof(font
), &font
))
1096 index
= metadc_create_font( metadc
, hfont
, &font
);
1099 GDI_hdc_using_object( hfont
, hdc
, METADC_DeleteObject
);
1101 if (!metadc_select_object( hdc
, index
)) return 0;
1103 metadc
->font
= hfont
;
1107 static UINT16
metadc_create_pen( struct metadc
*metadc
, HPEN pen
, LOGPEN16
*logpen
)
1109 char buffer
[FIELD_OFFSET(METARECORD
, rdParm
[sizeof(*logpen
) / sizeof(WORD
)])];
1110 METARECORD
*mr
= (METARECORD
*)&buffer
;
1112 mr
->rdSize
= sizeof(buffer
) / sizeof(WORD
);
1113 mr
->rdFunction
= META_CREATEPENINDIRECT
;
1114 memcpy( mr
->rdParm
, logpen
, sizeof(*logpen
) );
1115 if (!metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) )) return 0;
1116 return metadc_add_handle( metadc
, pen
);
1119 static HPEN
METADC_SelectPen( HDC hdc
, HPEN hpen
)
1121 struct metadc
*metadc
= get_metadc_ptr( hdc
);
1126 index
= metadc_find_object( metadc
, hpen
);
1129 /* must be an extended pen */
1130 INT size
= GetObjectW( hpen
, 0, NULL
);
1132 if (!size
) return 0;
1134 if (size
== sizeof(LOGPEN
))
1138 GetObjectW( hpen
, sizeof(pen
), &pen
);
1139 logpen
.lopnStyle
= pen
.lopnStyle
;
1140 logpen
.lopnWidth
.x
= pen
.lopnWidth
.x
;
1141 logpen
.lopnWidth
.y
= pen
.lopnWidth
.y
;
1142 logpen
.lopnColor
= pen
.lopnColor
;
1144 else /* must be an extended pen */
1146 EXTLOGPEN
*elp
= HeapAlloc( GetProcessHeap(), 0, size
);
1148 GetObjectW( hpen
, size
, elp
);
1149 /* FIXME: add support for user style pens */
1150 logpen
.lopnStyle
= elp
->elpPenStyle
;
1151 logpen
.lopnWidth
.x
= elp
->elpWidth
;
1152 logpen
.lopnWidth
.y
= 0;
1153 logpen
.lopnColor
= elp
->elpColor
;
1155 HeapFree( GetProcessHeap(), 0, elp
);
1158 index
= metadc_create_pen( metadc
, hpen
, &logpen
);
1161 GDI_hdc_using_object( hpen
, hdc
, METADC_DeleteObject
);
1164 if (!metadc_select_object( hdc
, index
)) return 0;
1170 static BOOL
metadc_create_palette( struct metadc
*metadc
, HPALETTE palette
,
1171 LOGPALETTE
*log_palette
, int sizeofPalette
)
1177 mr
= HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
) );
1178 if (!mr
) return FALSE
;
1179 mr
->rdSize
= (sizeof(METARECORD
) + sizeofPalette
- sizeof(WORD
)) / sizeof(WORD
);
1180 mr
->rdFunction
= META_CREATEPALETTE
;
1181 memcpy(&(mr
->rdParm
), log_palette
, sizeofPalette
);
1182 if (!metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) ))
1184 HeapFree(GetProcessHeap(), 0, mr
);
1188 mr
->rdSize
= sizeof(METARECORD
) / sizeof(WORD
);
1189 mr
->rdFunction
= META_SELECTPALETTE
;
1191 if ((index
= metadc_add_handle( metadc
, palette
)) == -1) ret
= FALSE
;
1194 mr
->rdParm
[0] = index
;
1195 ret
= metadc_write_record( metadc
, mr
, mr
->rdSize
* sizeof(WORD
) );
1197 HeapFree( GetProcessHeap(), 0, mr
);
1201 BOOL
METADC_SelectPalette( HDC hdc
, HPALETTE palette
)
1203 struct metadc
*metadc
;
1204 PLOGPALETTE log_palette
;
1209 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
1210 GetObjectA( palette
, sizeof(WORD
), &count
);
1211 if (!count
) return 0;
1213 size
= sizeof(LOGPALETTE
) + (count
- 1) * sizeof(PALETTEENTRY
);
1214 log_palette
= HeapAlloc( GetProcessHeap(), 0, size
);
1215 if (!log_palette
) return 0;
1217 log_palette
->palVersion
= 0x300;
1218 log_palette
->palNumEntries
= count
;
1220 GetPaletteEntries( palette
, 0, count
, log_palette
->palPalEntry
);
1222 ret
= metadc_create_palette( metadc
, palette
, log_palette
, size
);
1224 HeapFree( GetProcessHeap(), 0, log_palette
);
1228 BOOL
METADC_RealizePalette( HDC hdc
)
1230 return metadc_param0( hdc
, META_REALIZEPALETTE
);
1233 HGDIOBJ
METADC_SelectObject( HDC hdc
, HGDIOBJ obj
)
1235 switch (gdi_handle_type( obj
))
1237 case NTGDI_OBJ_BRUSH
:
1238 return METADC_SelectBrush( hdc
, obj
);
1239 case NTGDI_OBJ_FONT
:
1240 return METADC_SelectFont( hdc
, obj
);
1242 case NTGDI_OBJ_EXTPEN
:
1243 return METADC_SelectPen( hdc
, obj
);
1245 SetLastError( ERROR_INVALID_FUNCTION
);
1250 BOOL
METADC_ExtEscape( HDC hdc
, INT escape
, INT input_size
, const void *input
,
1251 INT output_size
, void *output
)
1257 if (output_size
) return FALSE
; /* escapes that require output cannot work in metafiles */
1259 len
= sizeof(*mr
) + sizeof(WORD
) + ((input_size
+ 1) & ~1);
1260 if (!(mr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
))) return FALSE
;
1261 mr
->rdSize
= len
/ sizeof(WORD
);
1262 mr
->rdFunction
= META_ESCAPE
;
1263 mr
->rdParm
[0] = escape
;
1264 mr
->rdParm
[1] = input_size
;
1265 memcpy( &mr
->rdParm
[2], input
, input_size
);
1266 ret
= metadc_record( hdc
, mr
, len
);
1267 HeapFree(GetProcessHeap(), 0, mr
);
1271 INT
METADC_GetDeviceCaps( HDC hdc
, INT cap
)
1273 if (!get_metadc_ptr( hdc
)) return 0;
1282 TRACE(" unsupported capability %d, will return 0\n", cap
);
1287 static void metadc_free( struct metadc
*metadc
)
1291 CloseHandle( metadc
->hFile
);
1292 HeapFree( GetProcessHeap(), 0, metadc
->mh
);
1293 for(index
= 0; index
< metadc
->handles_size
; index
++)
1294 if(metadc
->handles
[index
])
1295 GDI_hdc_not_using_object( metadc
->handles
[index
], metadc
->hdc
);
1296 HeapFree( GetProcessHeap(), 0, metadc
->handles
);
1297 HeapFree( GetProcessHeap(), 0, metadc
);
1300 BOOL
METADC_DeleteDC( HDC hdc
)
1302 struct metadc
*metadc
;
1304 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
1305 if (!NtGdiDeleteClientObj( hdc
)) return FALSE
;
1306 metadc_free( metadc
);
1310 /**********************************************************************
1311 * CreateMetaFileW (GDI32.@)
1313 * Create a new DC and associate it with a metafile. Pass a filename
1314 * to create a disk-based metafile, NULL to create a memory metafile.
1316 HDC WINAPI
CreateMetaFileW( const WCHAR
*filename
)
1318 struct metadc
*metadc
;
1321 TRACE( "%s\n", debugstr_w(filename
) );
1323 if (!(hdc
= NtGdiCreateClientObj( NTGDI_OBJ_METADC
))) return NULL
;
1325 metadc
= HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc
) );
1328 NtGdiDeleteClientObj( hdc
);
1331 if (!(metadc
->mh
= HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc
->mh
) )))
1333 HeapFree( GetProcessHeap(), 0, metadc
);
1334 NtGdiDeleteClientObj( hdc
);
1339 set_gdi_client_ptr( hdc
, metadc
);
1341 metadc
->handles
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
1342 HANDLE_LIST_INC
* sizeof(metadc
->handles
[0]) );
1343 metadc
->handles_size
= HANDLE_LIST_INC
;
1344 metadc
->cur_handles
= 0;
1348 metadc
->mh
->mtHeaderSize
= sizeof(METAHEADER
) / sizeof(WORD
);
1349 metadc
->mh
->mtVersion
= 0x0300;
1350 metadc
->mh
->mtSize
= metadc
->mh
->mtHeaderSize
;
1351 metadc
->mh
->mtNoObjects
= 0;
1352 metadc
->mh
->mtMaxRecord
= 0;
1353 metadc
->mh
->mtNoParameters
= 0;
1354 metadc
->mh
->mtType
= METAFILE_MEMORY
;
1356 metadc
->pen
= GetStockObject( BLACK_PEN
);
1357 metadc
->brush
= GetStockObject( WHITE_BRUSH
);
1358 metadc
->font
= GetStockObject( DEVICE_DEFAULT_FONT
);
1360 if (filename
) /* disk based metafile */
1362 HANDLE file
= CreateFileW( filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1363 if (file
== INVALID_HANDLE_VALUE
)
1365 HeapFree( GetProcessHeap(), 0, metadc
);
1366 NtGdiDeleteClientObj( hdc
);
1369 metadc
->hFile
= file
;
1372 TRACE( "returning %p\n", hdc
);
1376 /**********************************************************************
1377 * CreateMetaFileA (GDI32.@)
1379 HDC WINAPI
CreateMetaFileA( const char *filename
)
1385 if (!filename
) return CreateMetaFileW( NULL
);
1387 len
= MultiByteToWideChar( CP_ACP
, 0, filename
, -1, NULL
, 0 );
1388 filenameW
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
1389 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, filenameW
, len
);
1391 hdc
= CreateMetaFileW( filenameW
);
1393 HeapFree( GetProcessHeap(), 0, filenameW
);
1397 /******************************************************************
1398 * CloseMetaFile (GDI32.@)
1400 * Stop recording graphics operations in metafile associated with
1401 * hdc and retrieve metafile.
1403 HMETAFILE WINAPI
CloseMetaFile( HDC hdc
)
1405 struct metadc
*metadc
;
1406 DWORD bytes_written
;
1409 TRACE( "(%p)\n", hdc
);
1411 if (!(metadc
= get_metadc_ptr( hdc
))) return FALSE
;
1413 /* Construct the end of metafile record - this is documented
1414 * in SDK Knowledgebase Q99334.
1416 if (!metadc_param0( hdc
, META_EOF
)) return FALSE
;
1417 if (!NtGdiDeleteClientObj( hdc
)) return FALSE
;
1419 if (metadc
->hFile
&& !WriteFile( metadc
->hFile
, metadc
->mh
, metadc
->mh
->mtSize
* sizeof(WORD
),
1420 &bytes_written
, NULL
))
1422 metadc_free( metadc
);
1426 /* Now allocate a global handle for the metafile */
1427 hmf
= MF_Create_HMETAFILE( metadc
->mh
);
1428 if (hmf
) metadc
->mh
= NULL
; /* So it won't be deleted */
1429 metadc_free( metadc
);