uiautomationcore: Initialize VARIANT in test_uia_prov_from_acc_properties() (Coverity).
[wine.git] / dlls / gdi32 / metadc.c
blob2f5842ea90aa1055d7ffdbad9fe557eddca9933a
1 /*
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
23 #include <stdarg.h>
25 #include "gdi_private.h"
26 #include "winnls.h"
27 #include "wine/wingdi16.h"
29 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
34 struct metadc
36 HDC hdc;
37 METAHEADER *mh; /* Pointer to metafile header */
38 UINT handles_size, cur_handles;
39 HGDIOBJ *handles;
40 HANDLE hFile; /* Handle for disk based MetaFile */
41 HPEN pen;
42 HBRUSH brush;
43 HFONT font;
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 );
52 return metafile;
55 static BOOL metadc_write_record( struct metadc *metadc, METARECORD *mr, unsigned int rlen )
57 DWORD len, size;
58 METAHEADER *mh;
60 len = metadc->mh->mtSize * sizeof(WORD) + rlen;
61 size = HeapSize( GetProcessHeap(), 0, metadc->mh );
62 if (len > size)
64 size += size / sizeof(WORD) + rlen;
65 mh = HeapReAlloc( GetProcessHeap(), 0, metadc->mh, size );
66 if (!mh) return FALSE;
67 metadc->mh = mh;
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) );
73 return TRUE;
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 )
86 METARECORD mr;
88 mr.rdSize = FIELD_OFFSET(METARECORD, rdParm[0]) / sizeof(WORD);
89 mr.rdFunction = func;
90 return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) );
93 static BOOL metadc_param1( HDC hdc, short func, short param )
95 METARECORD mr;
97 mr.rdSize = sizeof(mr) / sizeof(WORD);
98 mr.rdFunction = func;
99 mr.rdParm[0] = param;
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,
148 short param6 )
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 )
369 BOOL ret;
370 DWORD len;
371 METARECORD *mr;
373 len = sizeof(METARECORD) + count * 4;
374 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
375 return FALSE;
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);
383 return ret;
386 BOOL METADC_Polyline( HDC hdc, const POINT *pt, INT count )
388 int i;
389 POINTS *pts;
390 BOOL ret;
392 pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * count );
393 if(!pts) return FALSE;
394 for (i=count;i--;)
396 pts[i].x = pt[i].x;
397 pts[i].y = pt[i].y;
399 ret = metadc_poly( hdc, META_POLYLINE, pts, count );
401 HeapFree( GetProcessHeap(), 0, pts );
402 return ret;
405 BOOL METADC_Polygon( HDC hdc, const POINT *pt, INT count )
407 int i;
408 POINTS *pts;
409 BOOL ret;
411 pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * count );
412 if(!pts) return FALSE;
413 for (i = count; i--;)
415 pts[i].x = pt[i].x;
416 pts[i].y = pt[i].y;
418 ret = metadc_poly( hdc, META_POLYGON, pts, count );
420 HeapFree( GetProcessHeap(), 0, pts );
421 return ret;
424 BOOL METADC_PolyPolygon( HDC hdc, const POINT *pt, const INT *counts, UINT polygons )
426 BOOL ret;
427 DWORD len;
428 METARECORD *mr;
429 unsigned int i,j;
430 POINTS *pts;
431 INT16 totalpoint16 = 0;
432 INT16 * pointcounts;
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--;)
448 pts[j].x = pt[j].x;
449 pts[j].y = pt[j].y;
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 );
459 return FALSE;
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);
472 return ret;
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 )
482 UINT16 index;
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,
490 metadc->handles,
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 )
504 BOOL ret = FALSE;
506 if (index < metadc->handles_size && metadc->handles[index])
508 metadc->handles[index] = 0;
509 metadc->cur_handles--;
510 ret = TRUE;
512 return ret;
515 static INT16 metadc_create_brush( struct metadc *metadc, HBRUSH brush )
517 DWORD size;
518 METARECORD *mr;
519 LOGBRUSH logbrush;
520 BOOL r;
522 if (!GetObjectA( brush, sizeof(logbrush), &logbrush )) return -1;
524 switch (logbrush.lbStyle)
526 case BS_SOLID:
527 case BS_NULL:
528 case BS_HATCHED:
530 LOGBRUSH16 lb16;
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) );
540 break;
542 case BS_PATTERN:
543 case BS_DIBPATTERN:
545 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
546 BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer;
547 DWORD info_size;
548 UINT usage;
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;
565 break;
568 default:
569 FIXME( "Unknown brush style %x\n", logbrush.lbStyle );
570 return 0;
573 r = metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) );
574 HeapFree(GetProcessHeap(), 0, mr);
575 if (!r) return -1;
576 done:
577 return metadc_add_handle( metadc, brush );
580 static INT16 metadc_create_region( struct metadc *metadc, HRGN hrgn )
582 DWORD len;
583 METARECORD *mr;
584 RGNDATA *rgndata;
585 RECT *cur_rect, *end_rect;
586 WORD bands = 0, max_bounds = 0;
587 WORD *param, *start_band;
588 BOOL ret;
590 if (!(len = NtGdiGetRegionData( hrgn, 0, NULL ))) return -1;
591 if (!(rgndata = HeapAlloc( GetProcessHeap(), 0, len )))
593 WARN( "Can't alloc rgndata buffer\n" );
594 return -1;
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 );
607 return -1;
610 param = mr->rdParm + 11;
611 start_band = NULL;
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;
621 else
623 if (start_band)
625 *start_band = param - start_band - 3;
626 *param++ = *start_band;
627 if (*start_band > max_bounds)
628 max_bounds = *start_band;
629 bands++;
631 start_band = param++;
632 *param++ = cur_rect->top;
633 *param++ = cur_rect->bottom;
634 *param++ = cur_rect->left;
635 *param++ = cur_rect->right;
639 if (start_band)
641 *start_band = param - start_band - 3;
642 *param++ = *start_band;
643 if (*start_band > max_bounds)
644 max_bounds = *start_band;
645 bands++;
648 mr->rdParm[0] = 0;
649 mr->rdParm[1] = 6;
650 mr->rdParm[2] = 0x2f6;
651 mr->rdParm[3] = 0;
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 );
664 if (!ret)
666 WARN("MFDRV_WriteRecord failed\n");
667 return -1;
669 return metadc_add_handle( metadc, hrgn );
672 BOOL METADC_PaintRgn( HDC hdc, HRGN hrgn )
674 struct metadc *metadc;
675 INT16 index;
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;
685 INT16 index;
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;
695 INT16 rgn, brush;
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;
709 INT16 rgn, brush;
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;
732 BITMAPINFO *bmi;
733 METARECORD *mr;
734 HBITMAP bitmap;
735 BOOL ret;
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;
741 if (bpp <= 8)
742 bmi_size = sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD);
743 else if (bpp == 16 || bpp == 32)
744 bmi_size = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD);
745 else
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 );
759 if (ret)
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);
779 return ret;
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,
791 DWORD rop )
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;
804 METARECORD *mr;
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 );
825 return height_src;
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;
835 METARECORD *mr;
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 );
854 return lines;
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 )
860 BOOL ret;
861 DWORD len;
862 METARECORD *mr;
863 BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE);
865 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
866 + sizeof(UINT16);
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;
873 mr->rdParm[0] = y;
874 mr->rdParm[1] = x;
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 );
879 if (dx)
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 );
883 return ret;
886 BOOL METADC_ExtTextOut( HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
887 const WCHAR *str, UINT count, const INT *dx )
889 RECT16 rect16;
890 LPINT16 lpdx16 = NULL;
891 BOOL ret;
892 unsigned int i, j;
893 char *ascii;
894 DWORD len;
895 CHARSETINFO csi;
896 int charset = GetTextCharset( hdc );
897 UINT cp = CP_ACP;
899 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET ))
900 cp = csi.ciACP;
901 else
903 switch(charset)
905 case OEM_CHARSET:
906 cp = GetOEMCP();
907 break;
908 case DEFAULT_CHARSET:
909 cp = GetACP();
910 break;
912 case VISCII_CHARSET:
913 case TCVN_CHARSET:
914 case KOI8_CHARSET:
915 case ISO3_CHARSET:
916 case ISO4_CHARSET:
917 case ISO10_CHARSET:
918 case CELTIC_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...
926 cp = CP_ACP;
927 break;
929 default:
930 FIXME("Can't find codepage for charset %d\n", charset);
931 break;
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) );
943 if (lprect)
945 rect16.left = lprect->left;
946 rect16.top = lprect->top;
947 rect16.right = lprect->right;
948 rect16.bottom = lprect->bottom;
951 if (dx)
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++];
958 lpdx16[i++] = 0;
960 else
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 );
967 return ret;
970 BOOL METADC_ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT mode )
972 struct metadc *metadc;
973 INT16 rgn;
974 INT ret;
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 );
984 return ret;
987 static INT16 metadc_find_object( struct metadc *metadc, HGDIOBJ obj )
989 INT16 index;
991 for (index = 0; index < metadc->handles_size; index++)
992 if (metadc->handles[index] == obj) return index;
994 return -1;
997 static void METADC_DeleteObject( HDC hdc, HGDIOBJ obj )
999 struct metadc *metadc = get_metadc_ptr( hdc );
1000 METARECORD mr;
1001 INT16 index;
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 );
1007 return;
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)
1022 METARECORD mr;
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 );
1033 INT16 index;
1034 HBRUSH ret;
1036 index = metadc_find_object( metadc, hbrush );
1037 if( index < 0 )
1039 index = metadc_create_brush( metadc, hbrush );
1040 if( index < 0 )
1041 return 0;
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;
1047 return ret;
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;
1054 LOGFONT16 *font16;
1055 INT written;
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 ))
1080 return 0;
1081 return metadc_add_handle( metadc, font );
1084 static HFONT METADC_SelectFont( HDC hdc, HFONT hfont )
1086 struct metadc *metadc = get_metadc_ptr( hdc );
1087 LOGFONTW font;
1088 INT16 index;
1089 HFONT ret;
1091 index = metadc_find_object( metadc, hfont );
1092 if (index < 0)
1094 if (!GetObjectW( hfont, sizeof(font), &font ))
1095 return 0;
1096 index = metadc_create_font( metadc, hfont, &font );
1097 if( index < 0 )
1098 return 0;
1099 GDI_hdc_using_object( hfont, hdc, METADC_DeleteObject );
1101 if (!metadc_select_object( hdc, index )) return 0;
1102 ret = metadc->font;
1103 metadc->font = hfont;
1104 return ret;
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 );
1122 LOGPEN16 logpen;
1123 INT16 index;
1124 HPEN ret;
1126 index = metadc_find_object( metadc, hpen );
1127 if (index < 0)
1129 /* must be an extended pen */
1130 INT size = GetObjectW( hpen, 0, NULL );
1132 if (!size) return 0;
1134 if (size == sizeof(LOGPEN))
1136 LOGPEN pen;
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 );
1159 if( index < 0 )
1160 return 0;
1161 GDI_hdc_using_object( hpen, hdc, METADC_DeleteObject );
1164 if (!metadc_select_object( hdc, index )) return 0;
1165 ret = metadc->pen;
1166 metadc->pen = hpen;
1167 return ret;
1170 static BOOL metadc_create_palette( struct metadc *metadc, HPALETTE palette,
1171 LOGPALETTE *log_palette, int sizeofPalette )
1173 int index;
1174 BOOL ret;
1175 METARECORD *mr;
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);
1185 return FALSE;
1188 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
1189 mr->rdFunction = META_SELECTPALETTE;
1191 if ((index = metadc_add_handle( metadc, palette )) == -1) ret = FALSE;
1192 else
1194 mr->rdParm[0] = index;
1195 ret = metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) );
1197 HeapFree( GetProcessHeap(), 0, mr );
1198 return ret;
1201 BOOL METADC_SelectPalette( HDC hdc, HPALETTE palette )
1203 struct metadc *metadc;
1204 PLOGPALETTE log_palette;
1205 WORD count = 0;
1206 BOOL ret;
1207 int size;
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 );
1225 return ret;
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 );
1241 case NTGDI_OBJ_PEN:
1242 case NTGDI_OBJ_EXTPEN:
1243 return METADC_SelectPen( hdc, obj );
1244 default:
1245 SetLastError( ERROR_INVALID_FUNCTION );
1246 return 0;
1250 BOOL METADC_ExtEscape( HDC hdc, INT escape, INT input_size, const void *input,
1251 INT output_size, void *output )
1253 METARECORD *mr;
1254 DWORD len;
1255 BOOL ret;
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);
1268 return ret;
1271 INT METADC_GetDeviceCaps( HDC hdc, INT cap )
1273 if (!get_metadc_ptr( hdc )) return 0;
1275 switch(cap)
1277 case TECHNOLOGY:
1278 return DT_METAFILE;
1279 case TEXTCAPS:
1280 return 0;
1281 default:
1282 TRACE(" unsupported capability %d, will return 0\n", cap );
1284 return 0;
1287 static void metadc_free( struct metadc *metadc )
1289 DWORD index;
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 );
1307 return TRUE;
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;
1319 HANDLE hdc;
1321 TRACE( "%s\n", debugstr_w(filename) );
1323 if (!(hdc = NtGdiCreateClientObj( NTGDI_OBJ_METADC ))) return NULL;
1325 metadc = HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc) );
1326 if (!metadc)
1328 NtGdiDeleteClientObj( hdc );
1329 return NULL;
1331 if (!(metadc->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc->mh) )))
1333 HeapFree( GetProcessHeap(), 0, metadc );
1334 NtGdiDeleteClientObj( hdc );
1335 return NULL;
1338 metadc->hdc = 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;
1346 metadc->hFile = 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 );
1367 return 0;
1369 metadc->hFile = file;
1372 TRACE( "returning %p\n", hdc );
1373 return hdc;
1376 /**********************************************************************
1377 * CreateMetaFileA (GDI32.@)
1379 HDC WINAPI CreateMetaFileA( const char *filename )
1381 LPWSTR filenameW;
1382 DWORD len;
1383 HDC hdc;
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 );
1394 return hdc;
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;
1407 HMETAFILE hmf;
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 );
1423 return FALSE;
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 );
1430 return hmf;