1 /*
2 * Metafile DC functions
3 *
4 * Copyright 1999 Huw D M Davies
5 * Copyright 1993, 1994, 1996 Alexandre Julliard
6 * Copyright 2021 Jacek Caban for CodeWeavers
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "wine/config.h"
24
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winnls.h"
33 #include "winerror.h"
34 #include "gdi_private.h"
35 #ifdef __REACTOS__
36 #include "wine/winternl.h"
37 #else
38 #include "winternl.h"
39 #endif
40 #include "wine/wingdi16.h"
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
44
45 struct metadc
46 {
47 HDC hdc;
48 METAHEADER *mh; /* Pointer to metafile header */
49 UINT handles_size, cur_handles;
50 HGDIOBJ *handles;
51 HANDLE hFile; /* Handle for disk based MetaFile */
52 HPEN pen;
53 HBRUSH brush;
54 HFONT font;
55 };
56
57 #define HANDLE_LIST_INC 20
58
59
get_metadc_ptr(HDC hdc)60 struct metadc *get_metadc_ptr( HDC hdc )
61 {
62 struct metadc *metafile = GdiGetClientObjLink(hdc);//get_gdi_client_ptr( hdc, NTGDI_OBJ_METADC );
63 if (!metafile) SetLastError( ERROR_INVALID_HANDLE );
64 return metafile;
65 }
66
metadc_write_record(struct metadc * metadc,METARECORD * mr,unsigned int rlen)67 static BOOL metadc_write_record( struct metadc *metadc, METARECORD *mr, unsigned int rlen )
68 {
69 DWORD len, size;
70 METAHEADER *mh;
71
72 len = metadc->mh->mtSize * sizeof(WORD) + rlen;
73 size = HeapSize( GetProcessHeap(), 0, metadc->mh );
74 if (len > size)
75 {
76 size += size / sizeof(WORD) + rlen;
77 mh = HeapReAlloc( GetProcessHeap(), 0, metadc->mh, size );
78 if (!mh) return FALSE;
79 metadc->mh = mh;
80 }
81 memcpy( (WORD *)metadc->mh + metadc->mh->mtSize, mr, rlen );
82
83 metadc->mh->mtSize += rlen / sizeof(WORD);
84 metadc->mh->mtMaxRecord = max( metadc->mh->mtMaxRecord, rlen / sizeof(WORD) );
85 return TRUE;
86 }
87
metadc_record(HDC hdc,METARECORD * mr,DWORD rlen)88 static BOOL metadc_record( HDC hdc, METARECORD *mr, DWORD rlen )
89 {
90 struct metadc *metadc;
91
92 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
93 return metadc_write_record( metadc, mr, rlen );
94 }
95
metadc_param0(HDC hdc,short func)96 static BOOL metadc_param0( HDC hdc, short func )
97 {
98 METARECORD mr;
99
100 mr.rdSize = FIELD_OFFSET(METARECORD, rdParm[0]) / sizeof(WORD);
101 mr.rdFunction = func;
102 return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) );
103 }
104
metadc_param1(HDC hdc,short func,short param)105 static BOOL metadc_param1( HDC hdc, short func, short param )
106 {
107 METARECORD mr;
108
109 mr.rdSize = sizeof(mr) / sizeof(WORD);
110 mr.rdFunction = func;
111 mr.rdParm[0] = param;
112 return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) );
113 }
114
metadc_param2(HDC hdc,short func,short param1,short param2)115 static BOOL metadc_param2( HDC hdc, short func, short param1, short param2 )
116 {
117 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm)
118 + 2*RTL_FIELD_SIZE(METARECORD, rdParm)];
119 METARECORD *mr = (METARECORD *)&buffer;
120
121 mr->rdSize = sizeof(buffer) / sizeof(WORD);
122 mr->rdFunction = func;
123 mr->rdParm[0] = param2;
124 mr->rdParm[1] = param1;
125 return metadc_record( hdc, mr, sizeof(buffer) );
126 }
127
metadc_param4(HDC hdc,short func,short param1,short param2,short param3,short param4)128 static BOOL metadc_param4( HDC hdc, short func, short param1, short param2,
129 short param3, short param4 )
130 {
131 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm)
132 + 4*RTL_FIELD_SIZE(METARECORD, rdParm)];
133 METARECORD *mr = (METARECORD *)&buffer;
134
135 mr->rdSize = sizeof(buffer) / sizeof(WORD);
136 mr->rdFunction = func;
137 mr->rdParm[0] = param4;
138 mr->rdParm[1] = param3;
139 mr->rdParm[2] = param2;
140 mr->rdParm[3] = param1;
141 return metadc_record( hdc, mr, sizeof(buffer) );
142 }
143
metadc_param5(HDC hdc,short func,short param1,short param2,short param3,short param4,short param5)144 static BOOL metadc_param5( HDC hdc, short func, short param1, short param2,
145 short param3, short param4, short param5 )
146 {
147 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm)
148 + 5*RTL_FIELD_SIZE(METARECORD, rdParm)];
149 METARECORD *mr = (METARECORD *)&buffer;
150
151 mr->rdSize = sizeof(buffer) / sizeof(WORD);
152 mr->rdFunction = func;
153 mr->rdParm[0] = param5;
154 mr->rdParm[1] = param4;
155 mr->rdParm[2] = param3;
156 mr->rdParm[3] = param2;
157 mr->rdParm[4] = param1;
158 return metadc_record( hdc, mr, sizeof(buffer) );
159 }
160
metadc_param6(HDC hdc,short func,short param1,short param2,short param3,short param4,short param5,short param6)161 static BOOL metadc_param6( HDC hdc, short func, short param1, short param2,
162 short param3, short param4, short param5,
163 short param6 )
164 {
165 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm)
166 + 6*RTL_FIELD_SIZE(METARECORD, rdParm)];
167 METARECORD *mr = (METARECORD *)&buffer;
168
169 mr->rdSize = sizeof(buffer) / sizeof(WORD);
170 mr->rdFunction = func;
171 mr->rdParm[0] = param6;
172 mr->rdParm[1] = param5;
173 mr->rdParm[2] = param4;
174 mr->rdParm[3] = param3;
175 mr->rdParm[4] = param2;
176 mr->rdParm[5] = param1;
177 return metadc_record( hdc, mr, sizeof(buffer) );
178 }
179
metadc_param8(HDC hdc,short func,short param1,short param2,short param3,short param4,short param5,short param6,short param7,short param8)180 static BOOL metadc_param8( HDC hdc, short func, short param1, short param2,
181 short param3, short param4, short param5,
182 short param6, short param7, short param8)
183 {
184 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm)
185 + 8*RTL_FIELD_SIZE(METARECORD, rdParm)];
186 METARECORD *mr = (METARECORD *)&buffer;
187
188 mr->rdSize = sizeof(buffer) / sizeof(WORD);
189 mr->rdFunction = func;
190 mr->rdParm[0] = param8;
191 mr->rdParm[1] = param7;
192 mr->rdParm[2] = param6;
193 mr->rdParm[3] = param5;
194 mr->rdParm[4] = param4;
195 mr->rdParm[5] = param3;
196 mr->rdParm[6] = param2;
197 mr->rdParm[7] = param1;
198 return metadc_record( hdc, mr, sizeof(buffer) );
199 }
200
METADC_SaveDC(HDC hdc)201 BOOL METADC_SaveDC( HDC hdc )
202 {
203 return metadc_param0( hdc, META_SAVEDC );
204 }
205
METADC_RestoreDC(HDC hdc,INT level)206 BOOL METADC_RestoreDC( HDC hdc, INT level )
207 {
208 return metadc_param1( hdc, META_RESTOREDC, level );
209 }
210
METADC_SetTextAlign(HDC hdc,UINT align)211 BOOL METADC_SetTextAlign( HDC hdc, UINT align )
212 {
213 return metadc_param2( hdc, META_SETTEXTALIGN, HIWORD(align), LOWORD(align) );
214 }
215
METADC_SetBkMode(HDC hdc,INT mode)216 BOOL METADC_SetBkMode( HDC hdc, INT mode )
217 {
218 return metadc_param1( hdc, META_SETBKMODE, (WORD)mode );
219 }
220
METADC_SetBkColor(HDC hdc,COLORREF color)221 BOOL METADC_SetBkColor( HDC hdc, COLORREF color )
222 {
223 return metadc_param2( hdc, META_SETBKCOLOR, HIWORD(color), LOWORD(color) );
224 }
225
METADC_SetTextColor(HDC hdc,COLORREF color)226 BOOL METADC_SetTextColor( HDC hdc, COLORREF color )
227 {
228 return metadc_param2( hdc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color) );
229 }
230
METADC_SetROP2(HDC hdc,INT rop)231 BOOL METADC_SetROP2( HDC hdc, INT rop )
232 {
233 return metadc_param1( hdc, META_SETROP2, (WORD)rop );
234 }
235
METADC_SetRelAbs(HDC hdc,INT mode)236 BOOL METADC_SetRelAbs( HDC hdc, INT mode )
237 {
238 return metadc_param1( hdc, META_SETRELABS, (WORD)mode );
239 }
240
METADC_SetPolyFillMode(HDC hdc,INT mode)241 BOOL METADC_SetPolyFillMode( HDC hdc, INT mode )
242 {
243 return metadc_param1( hdc, META_SETPOLYFILLMODE, mode );
244 }
245
METADC_SetStretchBltMode(HDC hdc,INT mode)246 BOOL METADC_SetStretchBltMode( HDC hdc, INT mode )
247 {
248 return metadc_param1( hdc, META_SETSTRETCHBLTMODE, mode );
249 }
250
METADC_IntersectClipRect(HDC hdc,INT left,INT top,INT right,INT bottom)251 BOOL METADC_IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
252 {
253 return metadc_param4( hdc, META_INTERSECTCLIPRECT, left, top, right, bottom );
254 }
255
METADC_ExcludeClipRect(HDC hdc,INT left,INT top,INT right,INT bottom)256 BOOL METADC_ExcludeClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
257 {
258 return metadc_param4( hdc, META_EXCLUDECLIPRECT, left, top, right, bottom );
259 }
260
METADC_OffsetClipRgn(HDC hdc,INT x,INT y)261 BOOL METADC_OffsetClipRgn( HDC hdc, INT x, INT y )
262 {
263 return metadc_param2( hdc, META_OFFSETCLIPRGN, x, y );
264 }
265
METADC_SetLayout(HDC hdc,DWORD layout)266 BOOL METADC_SetLayout( HDC hdc, DWORD layout )
267 {
268 return metadc_param2( hdc, META_SETLAYOUT, HIWORD(layout), LOWORD(layout) );
269 }
270
METADC_SetMapMode(HDC hdc,INT mode)271 BOOL METADC_SetMapMode( HDC hdc, INT mode )
272 {
273 return metadc_param1( hdc, META_SETMAPMODE, mode );
274 }
275
METADC_SetViewportExtEx(HDC hdc,INT x,INT y)276 BOOL METADC_SetViewportExtEx( HDC hdc, INT x, INT y )
277 {
278 return metadc_param2( hdc, META_SETVIEWPORTEXT, x, y );
279 }
280
METADC_SetViewportOrgEx(HDC hdc,INT x,INT y)281 BOOL METADC_SetViewportOrgEx( HDC hdc, INT x, INT y )
282 {
283 return metadc_param2( hdc, META_SETVIEWPORTORG, x, y );
284 }
285
METADC_SetWindowExtEx(HDC hdc,INT x,INT y)286 BOOL METADC_SetWindowExtEx( HDC hdc, INT x, INT y )
287 {
288 return metadc_param2( hdc, META_SETWINDOWEXT, x, y );
289 }
290
METADC_SetWindowOrgEx(HDC hdc,INT x,INT y)291 BOOL METADC_SetWindowOrgEx( HDC hdc, INT x, INT y )
292 {
293 return metadc_param2( hdc, META_SETWINDOWORG, x, y );
294 }
295
METADC_OffsetViewportOrgEx(HDC hdc,INT x,INT y)296 BOOL METADC_OffsetViewportOrgEx( HDC hdc, INT x, INT y )
297 {
298 return metadc_param2( hdc, META_OFFSETVIEWPORTORG, x, y );
299 }
300
METADC_OffsetWindowOrgEx(HDC hdc,INT x,INT y)301 BOOL METADC_OffsetWindowOrgEx( HDC hdc, INT x, INT y )
302 {
303 return metadc_param2( hdc, META_OFFSETWINDOWORG, x, y );
304 }
305
METADC_ScaleViewportExtEx(HDC hdc,INT x_num,INT x_denom,INT y_num,INT y_denom)306 BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT y_denom )
307 {
308 return metadc_param4( hdc, META_SCALEVIEWPORTEXT, x_num, x_denom, y_num, y_denom );
309 }
310
METADC_ScaleWindowExtEx(HDC hdc,INT x_num,INT x_denom,INT y_num,INT y_denom)311 BOOL METADC_ScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT y_denom )
312 {
313 return metadc_param4( hdc, META_SCALEWINDOWEXT, x_num, x_denom, y_num, y_denom );
314 }
315
METADC_SetTextJustification(HDC hdc,INT extra,INT breaks)316 BOOL METADC_SetTextJustification( HDC hdc, INT extra, INT breaks )
317 {
318 return metadc_param2( hdc, META_SETTEXTJUSTIFICATION, extra, breaks );
319 }
320
METADC_SetTextCharacterExtra(HDC hdc,INT extra)321 BOOL METADC_SetTextCharacterExtra( HDC hdc, INT extra )
322 {
323 return metadc_param1( hdc, META_SETTEXTCHAREXTRA, extra );
324 }
325
METADC_SetMapperFlags(HDC hdc,DWORD flags)326 BOOL METADC_SetMapperFlags( HDC hdc, DWORD flags )
327 {
328 return metadc_param2( hdc, META_SETMAPPERFLAGS, HIWORD(flags), LOWORD(flags) );
329 }
330
METADC_MoveTo(HDC hdc,INT x,INT y)331 BOOL METADC_MoveTo( HDC hdc, INT x, INT y )
332 {
333 return metadc_param2( hdc, META_MOVETO, x, y );
334 }
335
METADC_LineTo(HDC hdc,INT x,INT y)336 BOOL METADC_LineTo( HDC hdc, INT x, INT y )
337 {
338 return metadc_param2( hdc, META_LINETO, x, y );
339 }
340
METADC_Arc(HDC hdc,INT left,INT top,INT right,INT bottom,INT xstart,INT ystart,INT xend,INT yend)341 BOOL METADC_Arc( HDC hdc, INT left, INT top, INT right, INT bottom,
342 INT xstart, INT ystart, INT xend, INT yend )
343 {
344 return metadc_param8( hdc, META_ARC, left, top, right, bottom,
345 xstart, ystart, xend, yend );
346 }
347
METADC_Pie(HDC hdc,INT left,INT top,INT right,INT bottom,INT xstart,INT ystart,INT xend,INT yend)348 BOOL METADC_Pie( HDC hdc, INT left, INT top, INT right, INT bottom,
349 INT xstart, INT ystart, INT xend, INT yend )
350 {
351 return metadc_param8( hdc, META_PIE, left, top, right, bottom,
352 xstart, ystart, xend, yend );
353 }
354
METADC_Chord(HDC hdc,INT left,INT top,INT right,INT bottom,INT xstart,INT ystart,INT xend,INT yend)355 BOOL METADC_Chord( HDC hdc, INT left, INT top, INT right, INT bottom,
356 INT xstart, INT ystart, INT xend, INT yend )
357 {
358 return metadc_param8( hdc, META_CHORD, left, top, right, bottom,
359 xstart, ystart, xend, yend );
360 }
361
METADC_Ellipse(HDC hdc,INT left,INT top,INT right,INT bottom)362 BOOL METADC_Ellipse( HDC hdc, INT left, INT top, INT right, INT bottom )
363 {
364 return metadc_param4( hdc, META_ELLIPSE, left, top, right, bottom );
365 }
366
METADC_Rectangle(HDC hdc,INT left,INT top,INT right,INT bottom)367 BOOL METADC_Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom )
368 {
369 return metadc_param4( hdc, META_RECTANGLE, left, top, right, bottom );
370 }
371
METADC_RoundRect(HDC hdc,INT left,INT top,INT right,INT bottom,INT ell_width,INT ell_height)372 BOOL METADC_RoundRect( HDC hdc, INT left, INT top, INT right,
373 INT bottom, INT ell_width, INT ell_height )
374 {
375 return metadc_param6( hdc, META_ROUNDRECT, left, top, right, bottom,
376 ell_width, ell_height );
377 }
378
METADC_SetPixel(HDC hdc,INT x,INT y,COLORREF color)379 BOOL METADC_SetPixel( HDC hdc, INT x, INT y, COLORREF color )
380 {
381 return metadc_param4( hdc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color) );
382 }
383
metadc_poly(HDC hdc,short func,POINTS * pt,short count)384 static BOOL metadc_poly( HDC hdc, short func, POINTS *pt, short count )
385 {
386 BOOL ret;
387 DWORD len;
388 METARECORD *mr;
389
390 len = sizeof(METARECORD) + count * 4;
391 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
392 return FALSE;
393
394 mr->rdSize = len / 2;
395 mr->rdFunction = func;
396 *(mr->rdParm) = count;
397 memcpy(mr->rdParm + 1, pt, count * 4);
398 ret = metadc_record( hdc, mr, mr->rdSize * 2);
399 HeapFree( GetProcessHeap(), 0, mr);
400 return ret;
401 }
402
METADC_Polyline(HDC hdc,const POINT * pt,INT count)403 BOOL METADC_Polyline( HDC hdc, const POINT *pt, INT count )
404 {
405 int i;
406 POINTS *pts;
407 BOOL ret;
408
409 pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * count );
410 if(!pts) return FALSE;
411 for (i=count;i--;)
412 {
413 pts[i].x = pt[i].x;
414 pts[i].y = pt[i].y;
415 }
416 ret = metadc_poly( hdc, META_POLYLINE, pts, count );
417
418 HeapFree( GetProcessHeap(), 0, pts );
419 return ret;
420 }
421
METADC_Polygon(HDC hdc,const POINT * pt,INT count)422 BOOL METADC_Polygon( HDC hdc, const POINT *pt, INT count )
423 {
424 int i;
425 POINTS *pts;
426 BOOL ret;
427
428 pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * count );
429 if(!pts) return FALSE;
430 for (i = count; i--;)
431 {
432 pts[i].x = pt[i].x;
433 pts[i].y = pt[i].y;
434 }
435 ret = metadc_poly( hdc, META_POLYGON, pts, count );
436
437 HeapFree( GetProcessHeap(), 0, pts );
438 return ret;
439 }
440
METADC_PolyPolygon(HDC hdc,const POINT * pt,const INT * counts,UINT polygons)441 BOOL METADC_PolyPolygon( HDC hdc, const POINT *pt, const INT *counts, UINT polygons )
442 {
443 BOOL ret;
444 DWORD len;
445 METARECORD *mr;
446 unsigned int i,j;
447 POINTS *pts;
448 INT16 totalpoint16 = 0;
449 INT16 * pointcounts;
450
451 for (i = 0; i < polygons; i++)
452 totalpoint16 += counts[i];
453
454 /* allocate space for all points */
455 pts=HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * totalpoint16 );
456 pointcounts = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16) * totalpoint16 );
457
458 /* copy point counts */
459 for (i = 0; i < polygons; i++)
460 pointcounts[i] = counts[i];
461
462 /* convert all points */
463 for (j = totalpoint16; j--;)
464 {
465 pts[j].x = pt[j].x;
466 pts[j].y = pt[j].y;
467 }
468
469 len = sizeof(METARECORD) + sizeof(WORD) + polygons * sizeof(INT16) +
470 totalpoint16 * sizeof(*pts);
471
472 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
473 {
474 HeapFree( GetProcessHeap(), 0, pts );
475 HeapFree( GetProcessHeap(), 0, pointcounts );
476 return FALSE;
477 }
478
479 mr->rdSize = len / sizeof(WORD);
480 mr->rdFunction = META_POLYPOLYGON;
481 *mr->rdParm = polygons;
482 memcpy( mr->rdParm + 1, pointcounts, polygons * sizeof(INT16) );
483 memcpy( mr->rdParm + 1+polygons, pts , totalpoint16 * sizeof(*pts) );
484 ret = metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) );
485
486 HeapFree( GetProcessHeap(), 0, pts );
487 HeapFree( GetProcessHeap(), 0, pointcounts );
488 HeapFree( GetProcessHeap(), 0, mr);
489 return ret;
490 }
491
METADC_ExtFloodFill(HDC hdc,INT x,INT y,COLORREF color,UINT fill_type)492 BOOL METADC_ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, UINT fill_type )
493 {
494 return metadc_param5( hdc, META_EXTFLOODFILL, x, y, HIWORD(color), LOWORD(color), fill_type );
495 }
496
metadc_add_handle(struct metadc * metadc,HGDIOBJ obj)497 static UINT metadc_add_handle( struct metadc *metadc, HGDIOBJ obj )
498 {
499 UINT16 index;
500
501 for (index = 0; index < metadc->handles_size; index++)
502 if (metadc->handles[index] == 0) break;
503 if(index == metadc->handles_size)
504 {
505 metadc->handles_size += HANDLE_LIST_INC;
506 metadc->handles = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
507 metadc->handles,
508 metadc->handles_size * sizeof(metadc->handles[0]) );
509 }
510 metadc->handles[index] = get_full_gdi_handle( obj );
511
512 metadc->cur_handles++;
513 if (metadc->cur_handles > metadc->mh->mtNoObjects)
514 metadc->mh->mtNoObjects++;
515
516 return index ; /* index 0 is not reserved for metafiles */
517 }
518
metadc_remove_handle(struct metadc * metadc,UINT index)519 static BOOL metadc_remove_handle( struct metadc *metadc, UINT index )
520 {
521 BOOL ret = FALSE;
522
523 if (index < metadc->handles_size && metadc->handles[index])
524 {
525 metadc->handles[index] = 0;
526 metadc->cur_handles--;
527 ret = TRUE;
528 }
529 return ret;
530 }
531
metadc_create_brush(struct metadc * metadc,HBRUSH brush)532 static INT16 metadc_create_brush( struct metadc *metadc, HBRUSH brush )
533 {
534 DWORD size;
535 METARECORD *mr;
536 LOGBRUSH logbrush;
537 BOOL r;
538
539 if (!GetObjectA( brush, sizeof(logbrush), &logbrush )) return -1;
540
541 switch (logbrush.lbStyle)
542 {
543 case BS_SOLID:
544 case BS_NULL:
545 case BS_HATCHED:
546 {
547 LOGBRUSH16 lb16;
548
549 lb16.lbStyle = logbrush.lbStyle;
550 lb16.lbColor = logbrush.lbColor;
551 lb16.lbHatch = logbrush.lbHatch;
552 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - sizeof(WORD);
553 mr = HeapAlloc( GetProcessHeap(), 0, size );
554 mr->rdSize = size / sizeof(WORD);
555 mr->rdFunction = META_CREATEBRUSHINDIRECT;
556 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16) );
557 break;
558 }
559 case BS_PATTERN:
560 case BS_DIBPATTERN:
561 {
562 unsigned char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors)
563 + 256*RTL_FIELD_SIZE(BITMAPINFO, bmiColors)];
564 BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer;
565 DWORD info_size;
566 UINT usage;
567
568 if (!get_brush_bitmap_info( brush, src_info, NULL, &usage )) goto done;
569
570 info_size = get_dib_info_size( src_info, usage );
571 size = FIELD_OFFSET( METARECORD, rdParm[2] ) +
572 info_size + src_info->bmiHeader.biSizeImage;
573
574 if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) goto done;
575 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
576 mr->rdSize = size / sizeof(WORD);
577 mr->rdParm[0] = logbrush.lbStyle;
578 mr->rdParm[1] = usage;
579 dst_info = (BITMAPINFO *)(mr->rdParm + 2);
580 get_brush_bitmap_info( brush, dst_info, (char *)dst_info + info_size, NULL );
581 if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount)
582 dst_info->bmiHeader.biClrUsed = 0;
583 break;
584 }
585
586 default:
587 FIXME( "Unknown brush style %x\n", logbrush.lbStyle );
588 return 0;
589 }
590
591 r = metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) );
592 HeapFree(GetProcessHeap(), 0, mr);
593 if (!r) return -1;
594 done:
595 return metadc_add_handle( metadc, brush );
596 }
597
metadc_create_region(struct metadc * metadc,HRGN hrgn)598 static INT16 metadc_create_region( struct metadc *metadc, HRGN hrgn )
599 {
600 DWORD len;
601 METARECORD *mr;
602 RGNDATA *rgndata;
603 RECT *cur_rect, *end_rect;
604 WORD bands = 0, max_bounds = 0;
605 WORD *param, *start_band;
606 BOOL ret;
607
608 if (!(len = GetRegionData( hrgn, 0, NULL ))) return -1;
609 if (!(rgndata = HeapAlloc( GetProcessHeap(), 0, len )))
610 {
611 WARN( "Can't alloc rgndata buffer\n" );
612 return -1;
613 }
614 GetRegionData( hrgn, len, rgndata );
615
616 /* Overestimate of length:
617 * Assume every rect is a separate band -> 6 WORDs per rect,
618 * see MF_Play_MetaCreateRegion for format details.
619 */
620 len = sizeof(METARECORD) + 20 + rgndata->rdh.nCount * 12;
621 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
622 {
623 WARN( "Can't alloc METARECORD buffer\n" );
624 HeapFree( GetProcessHeap(), 0, rgndata );
625 return -1;
626 }
627
628 param = mr->rdParm + 11;
629 start_band = NULL;
630
631 end_rect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
632 for (cur_rect = (RECT *)rgndata->Buffer; cur_rect < end_rect; cur_rect++)
633 {
634 if (start_band && cur_rect->top == start_band[1])
635 {
636 *param++ = cur_rect->left;
637 *param++ = cur_rect->right;
638 }
639 else
640 {
641 if (start_band)
642 {
643 *start_band = param - start_band - 3;
644 *param++ = *start_band;
645 if (*start_band > max_bounds)
646 max_bounds = *start_band;
647 bands++;
648 }
649 start_band = param++;
650 *param++ = cur_rect->top;
651 *param++ = cur_rect->bottom;
652 *param++ = cur_rect->left;
653 *param++ = cur_rect->right;
654 }
655 }
656
657 if (start_band)
658 {
659 *start_band = param - start_band - 3;
660 *param++ = *start_band;
661 if (*start_band > max_bounds)
662 max_bounds = *start_band;
663 bands++;
664 }
665
666 mr->rdParm[0] = 0;
667 mr->rdParm[1] = 6;
668 mr->rdParm[2] = 0x2f6;
669 mr->rdParm[3] = 0;
670 mr->rdParm[4] = (WORD)((param - &mr->rdFunction) * sizeof(WORD));
671 mr->rdParm[5] = bands;
672 mr->rdParm[6] = max_bounds;
673 mr->rdParm[7] = rgndata->rdh.rcBound.left;
674 mr->rdParm[8] = rgndata->rdh.rcBound.top;
675 mr->rdParm[9] = rgndata->rdh.rcBound.right;
676 mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
677 mr->rdFunction = META_CREATEREGION;
678 mr->rdSize = param - (WORD *)mr;
679 ret = metadc_write_record( metadc, mr, mr->rdSize * 2 );
680 HeapFree( GetProcessHeap(), 0, mr );
681 HeapFree( GetProcessHeap(), 0, rgndata );
682 if (!ret)
683 {
684 WARN("MFDRV_WriteRecord failed\n");
685 return -1;
686 }
687 return metadc_add_handle( metadc, hrgn );
688 }
689
METADC_PaintRgn(HDC hdc,HRGN hrgn)690 BOOL METADC_PaintRgn( HDC hdc, HRGN hrgn )
691 {
692 struct metadc *metadc;
693 INT16 index;
694 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
695 index = metadc_create_region( metadc, hrgn );
696 if(index == -1) return FALSE;
697 return metadc_param1( hdc, META_PAINTREGION, index );
698 }
699
METADC_InvertRgn(HDC hdc,HRGN hrgn)700 BOOL METADC_InvertRgn( HDC hdc, HRGN hrgn )
701 {
702 struct metadc *metadc;
703 INT16 index;
704 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
705 index = metadc_create_region( metadc, hrgn );
706 if (index == -1) return FALSE;
707 return metadc_param1( hdc, META_INVERTREGION, index );
708 }
709
METADC_FillRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush)710 BOOL METADC_FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
711 {
712 struct metadc *metadc;
713 INT16 rgn, brush;
714
715 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
716
717 rgn = metadc_create_region( metadc, hrgn );
718 if (rgn == -1) return FALSE;
719 brush = metadc_create_brush( metadc, hbrush );
720 if (!brush) return FALSE;
721 return metadc_param2( hdc, META_FILLREGION, rgn, brush );
722 }
723
METADC_FrameRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush,INT x,INT y)724 BOOL METADC_FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, INT x, INT y )
725 {
726 struct metadc *metadc;
727 INT16 rgn, brush;
728
729 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
730 rgn = metadc_create_region( metadc, hrgn );
731 if (rgn == -1) return FALSE;
732 brush = metadc_create_brush( metadc, hbrush );
733 if (!brush) return FALSE;
734 return metadc_param4( hdc, META_FRAMEREGION, rgn, brush, x, y );
735 }
736
METADC_PatBlt(HDC hdc,INT left,INT top,INT width,INT height,DWORD rop)737 BOOL METADC_PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop )
738 {
739 return metadc_param6( hdc, META_PATBLT, left, top, width, height,
740 HIWORD(rop), LOWORD(rop) );
741 }
742
metadc_stretchblt(HDC hdc,INT x_dst,INT y_dst,INT width_dst,INT height_dst,HDC hdc_src,INT x_src,INT y_src,INT width_src,INT height_src,DWORD rop,WORD type)743 static BOOL metadc_stretchblt( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height_dst,
744 HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src,
745 DWORD rop, WORD type )
746 {
747 BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }};
748 UINT bmi_size, size, bpp;
749 int i = 0, bitmap_offset;
750 BITMAPINFO *bmi;
751 METARECORD *mr;
752 HBITMAP bitmap;
753 BOOL ret;
754
755 if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE;
756 if (!GetDIBits( hdc_src, bitmap, 0, INT_MAX, NULL, &src_info, DIB_RGB_COLORS )) return FALSE;
757
758 bpp = src_info.bmiHeader.biBitCount;
759 if (bpp <= 8)
760 bmi_size = sizeof(BITMAPINFOHEADER) + (1L << bpp) * sizeof(RGBQUAD);
761 else if (bpp == 16 || bpp == 32)
762 bmi_size = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD);
763 else
764 bmi_size = sizeof(BITMAPINFOHEADER);
765
766 bitmap_offset = type == META_DIBBITBLT ? 8 : 10;
767 size = FIELD_OFFSET( METARECORD, rdParm[bitmap_offset] ) + bmi_size +
768 src_info.bmiHeader.biSizeImage;
769 if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
770 mr->rdFunction = type;
771 bmi = (BITMAPINFO *)&mr->rdParm[bitmap_offset];
772 bmi->bmiHeader = src_info.bmiHeader;
773 TRACE( "size = %u rop=%x\n", size, rop );
774
775 ret = GetDIBits( hdc_src, bitmap, 0, src_info.bmiHeader.biHeight, (BYTE *)bmi + bmi_size,
776 bmi, DIB_RGB_COLORS );
777 if (ret)
778 {
779 mr->rdSize = size / sizeof(WORD);
780 mr->rdParm[i++] = LOWORD(rop);
781 mr->rdParm[i++] = HIWORD(rop);
782 if (bitmap_offset > 8)
783 {
784 mr->rdParm[i++] = height_src;
785 mr->rdParm[i++] = width_src;
786 }
787 mr->rdParm[i++] = y_src;
788 mr->rdParm[i++] = x_src;
789 mr->rdParm[i++] = height_dst;
790 mr->rdParm[i++] = width_dst;
791 mr->rdParm[i++] = y_dst;
792 mr->rdParm[i++] = x_dst;
793 ret = metadc_record( hdc, mr, size );
794 }
795
796 HeapFree( GetProcessHeap(), 0, mr);
797 return ret;
798 }
799
METADC_BitBlt(HDC hdc,INT x_dst,INT y_dst,INT width,INT height,HDC hdc_src,INT x_src,INT y_src,DWORD rop)800 BOOL METADC_BitBlt( HDC hdc, INT x_dst, INT y_dst, INT width, INT height,
801 HDC hdc_src, INT x_src, INT y_src, DWORD rop )
802 {
803 return metadc_stretchblt( hdc, x_dst, y_dst, width, height,
804 hdc_src, x_src, y_src, width, height, rop, META_DIBBITBLT );
805 }
806
METADC_StretchBlt(HDC hdc_dst,INT x_dst,INT y_dst,INT width_dst,INT height_dst,HDC hdc_src,INT x_src,INT y_src,INT width_src,INT height_src,DWORD rop)807 BOOL METADC_StretchBlt( HDC hdc_dst, INT x_dst, INT y_dst, INT width_dst, INT height_dst,
808 HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src,
809 DWORD rop )
810 {
811 return metadc_stretchblt( hdc_dst, x_dst, y_dst, width_dst, height_dst,
812 hdc_src, x_src, y_src, width_src, height_src, rop, META_DIBSTRETCHBLT );
813 }
814
METADC_StretchDIBits(HDC hdc,INT x_dst,INT y_dst,INT width_dst,INT height_dst,INT x_src,INT y_src,INT width_src,INT height_src,const void * bits,const BITMAPINFO * info,UINT usage,DWORD rop)815 INT METADC_StretchDIBits( HDC hdc, INT x_dst, INT y_dst, INT width_dst,
816 INT height_dst, INT x_src, INT y_src, INT width_src,
817 INT height_src, const void *bits,
818 const BITMAPINFO *info, UINT usage, DWORD rop )
819 {
820 DWORD infosize = get_dib_info_size( info, usage );
821 DWORD len = sizeof(METARECORD) + 10 * sizeof(WORD) + infosize + info->bmiHeader.biSizeImage;
822 METARECORD *mr;
823
824 if (!(mr = HeapAlloc( GetProcessHeap(), 0, len ))) return 0;
825
826 mr->rdSize = len / sizeof(WORD);
827 mr->rdFunction = META_STRETCHDIB;
828 mr->rdParm[0] = LOWORD(rop);
829 mr->rdParm[1] = HIWORD(rop);
830 mr->rdParm[2] = usage;
831 mr->rdParm[3] = height_src;
832 mr->rdParm[4] = width_src;
833 mr->rdParm[5] = y_src;
834 mr->rdParm[6] = x_src;
835 mr->rdParm[7] = height_dst;
836 mr->rdParm[8] = width_dst;
837 mr->rdParm[9] = y_dst;
838 mr->rdParm[10] = x_dst;
839 memcpy( mr->rdParm + 11, info, infosize );
840 memcpy( mr->rdParm + 11 + infosize / 2, bits, info->bmiHeader.biSizeImage );
841 metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) );
842 HeapFree( GetProcessHeap(), 0, mr );
843 return height_src;
844 }
845
METADC_SetDIBitsToDevice(HDC hdc,INT x_dst,INT y_dst,DWORD width,DWORD height,INT x_src,INT y_src,UINT startscan,UINT lines,const void * bits,const BITMAPINFO * info,UINT coloruse)846 INT METADC_SetDIBitsToDevice( HDC hdc, INT x_dst, INT y_dst, DWORD width, DWORD height,
847 INT x_src, INT y_src, UINT startscan, UINT lines,
848 const void *bits, const BITMAPINFO *info, UINT coloruse )
849
850 {
851 DWORD infosize = get_dib_info_size(info, coloruse);
852 DWORD len = sizeof(METARECORD) + 8 * sizeof(WORD) + infosize + info->bmiHeader.biSizeImage;
853 METARECORD *mr;
854
855 if (!(mr = HeapAlloc( GetProcessHeap(), 0, len ))) return 0;
856
857 mr->rdSize = len / sizeof(WORD);
858 mr->rdFunction = META_SETDIBTODEV;
859 mr->rdParm[0] = coloruse;
860 mr->rdParm[1] = lines;
861 mr->rdParm[2] = startscan;
862 mr->rdParm[3] = y_src;
863 mr->rdParm[4] = x_src;
864 mr->rdParm[5] = height;
865 mr->rdParm[6] = width;
866 mr->rdParm[7] = y_dst;
867 mr->rdParm[8] = x_dst;
868 memcpy( mr->rdParm + 9, info, infosize );
869 memcpy( mr->rdParm + 9 + infosize / sizeof(WORD), bits, info->bmiHeader.biSizeImage );
870 metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) );
871 HeapFree( GetProcessHeap(), 0, mr );
872 return lines;
873 }
874
metadc_text(HDC hdc,short x,short y,UINT16 flags,const RECT16 * rect,const char * str,short count,const INT16 * dx)875 static BOOL metadc_text( HDC hdc, short x, short y, UINT16 flags, const RECT16 *rect,
876 const char *str, short count, const INT16 *dx )
877 {
878 BOOL ret;
879 DWORD len;
880 METARECORD *mr;
881 BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE);
882
883 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
884 + sizeof(UINT16);
885 if (isrect) len += sizeof(RECT16);
886 if (dx) len += count * sizeof(INT16);
887 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) return FALSE;
888
889 mr->rdSize = len / sizeof(WORD);
890 mr->rdFunction = META_EXTTEXTOUT;
891 mr->rdParm[0] = y;
892 mr->rdParm[1] = x;
893 mr->rdParm[2] = count;
894 mr->rdParm[3] = flags;
895 if (isrect) memcpy( mr->rdParm + 4, rect, sizeof(RECT16) );
896 memcpy( mr->rdParm + (isrect ? 8 : 4), str, count );
897 if (dx)
898 memcpy( mr->rdParm + (isrect ? 8 : 4) + ((count + 1) >> 1), dx, count * sizeof(INT16) );
899 ret = metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) );
900 HeapFree( GetProcessHeap(), 0, mr );
901 return ret;
902 }
903
METADC_ExtTextOut(HDC hdc,INT x,INT y,UINT flags,const RECT * lprect,const WCHAR * str,UINT count,const INT * dx)904 BOOL METADC_ExtTextOut( HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
905 const WCHAR *str, UINT count, const INT *dx )
906 {
907 RECT16 rect16;
908 LPINT16 lpdx16 = NULL;
909 BOOL ret;
910 unsigned int i, j;
911 char *ascii;
912 DWORD len;
913 CHARSETINFO csi;
914 int charset = GetTextCharset( hdc );
915 UINT cp = CP_ACP;
916
917 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET ))
918 cp = csi.ciACP;
919 else
920 {
921 switch(charset)
922 {
923 case OEM_CHARSET:
924 cp = GetOEMCP();
925 break;
926 case DEFAULT_CHARSET:
927 cp = GetACP();
928 break;
929
930 case VISCII_CHARSET:
931 case TCVN_CHARSET:
932 case KOI8_CHARSET:
933 case ISO3_CHARSET:
934 case ISO4_CHARSET:
935 case ISO10_CHARSET:
936 case CELTIC_CHARSET:
937 /* FIXME: These have no place here, but because x11drv
938 enumerates fonts with these (made up) charsets some apps
939 might use them and then the FIXME below would become
940 annoying. Now we could pick the intended codepage for
941 each of these, but since it's broken anyway we'll just
942 use CP_ACP and hope it'll go away...
943 */
944 cp = CP_ACP;
945 break;
946
947 default:
948 FIXME("Can't find codepage for charset %d\n", charset);
949 break;
950 }
951 }
952
953
954 TRACE( "cp = %d\n", cp );
955 len = WideCharToMultiByte( cp, 0, str, count, NULL, 0, NULL, NULL );
956 ascii = HeapAlloc( GetProcessHeap(), 0, len );
957 WideCharToMultiByte( cp, 0, str, count, ascii, len, NULL, NULL );
958 TRACE( "mapped %s -> %s\n", debugstr_wn(str, count), debugstr_an(ascii, len) );
959
960
961 if (lprect)
962 {
963 rect16.left = lprect->left;
964 rect16.top = lprect->top;
965 rect16.right = lprect->right;
966 rect16.bottom = lprect->bottom;
967 }
968
969 if (dx)
970 {
971 lpdx16 = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16) * len );
972 for (i = j = 0; i < len; )
973 if (IsDBCSLeadByteEx( cp, ascii[i] ))
974 {
975 lpdx16[i++] = dx[j++];
976 lpdx16[i++] = 0;
977 }
978 else
979 lpdx16[i++] = dx[j++];
980 }
981
982 ret = metadc_text( hdc, x, y, flags, lprect ? &rect16 : NULL, ascii, len, lpdx16 );
983 HeapFree( GetProcessHeap(), 0, ascii );
984 HeapFree( GetProcessHeap(), 0, lpdx16 );
985 return ret;
986 }
987
METADC_ExtSelectClipRgn(HDC hdc,HRGN hrgn,INT mode)988 BOOL METADC_ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT mode )
989 {
990 struct metadc *metadc;
991 INT16 rgn;
992 INT ret;
993
994 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
995 if (mode != RGN_COPY) return ERROR;
996 if (!hrgn) return NULLREGION;
997 rgn = metadc_create_region( metadc, hrgn );
998 if(rgn == -1) return ERROR;
999 ret = metadc_param1( hdc, META_SELECTOBJECT, rgn ) ? NULLREGION : ERROR;
1000 metadc_param1( hdc, META_DELETEOBJECT, rgn );
1001 metadc_remove_handle( metadc, rgn );
1002 return ret;
1003 }
1004
metadc_find_object(struct metadc * metadc,HGDIOBJ obj)1005 static INT16 metadc_find_object( struct metadc *metadc, HGDIOBJ obj )
1006 {
1007 INT16 index;
1008
1009 for (index = 0; index < metadc->handles_size; index++)
1010 if (metadc->handles[index] == obj) return index;
1011
1012 return -1;
1013 }
1014
METADC_DeleteObject(HDC hdc,HGDIOBJ obj)1015 void METADC_DeleteObject( HDC hdc, HGDIOBJ obj )
1016 {
1017 struct metadc *metadc = get_metadc_ptr( hdc );
1018 METARECORD mr;
1019 INT16 index;
1020
1021 if ((index = metadc_find_object( metadc, obj )) < 0) return;
1022 if (obj == metadc->pen || obj == metadc->brush || obj == metadc->font)
1023 {
1024 WARN( "deleting selected object %p\n", obj );
1025 return;
1026 }
1027
1028 mr.rdSize = sizeof(mr) / sizeof(WORD);
1029 mr.rdFunction = META_DELETEOBJECT;
1030 mr.rdParm[0] = index;
1031
1032 metadc_write_record( metadc, &mr, mr.rdSize * sizeof(WORD) );
1033
1034 metadc->handles[index] = 0;
1035 metadc->cur_handles--;
1036 }
1037
metadc_select_object(HDC hdc,INT16 index)1038 static BOOL metadc_select_object( HDC hdc, INT16 index)
1039 {
1040 METARECORD mr;
1041
1042 mr.rdSize = sizeof mr / 2;
1043 mr.rdFunction = META_SELECTOBJECT;
1044 mr.rdParm[0] = index;
1045 return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) );
1046 }
1047
METADC_SelectBrush(HDC hdc,HBRUSH hbrush)1048 static HBRUSH METADC_SelectBrush( HDC hdc, HBRUSH hbrush )
1049 {
1050 struct metadc *metadc = get_metadc_ptr( hdc );
1051 INT16 index;
1052 HBRUSH ret;
1053
1054 index = metadc_find_object( metadc, hbrush );
1055 if( index < 0 )
1056 {
1057 index = metadc_create_brush( metadc, hbrush );
1058 if( index < 0 )
1059 return 0;
1060 GDI_hdc_using_object( hbrush, hdc );//, METADC_DeleteObject );
1061 }
1062 if (!metadc_select_object( hdc, index )) return 0;
1063 ret = metadc->brush;
1064 metadc->brush = hbrush;
1065 return ret;
1066 }
1067
metadc_create_font(struct metadc * metadc,HFONT font,LOGFONTW * logfont)1068 static UINT16 metadc_create_font( struct metadc *metadc, HFONT font, LOGFONTW *logfont )
1069 {
1070 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm) + sizeof(LOGFONT16)];
1071 METARECORD *mr = (METARECORD *)&buffer;
1072 LOGFONT16 *font16;
1073 INT written;
1074
1075 mr->rdSize = sizeof(buffer) / sizeof(WORD);
1076 mr->rdFunction = META_CREATEFONTINDIRECT;
1077 font16 = (LOGFONT16 *)&mr->rdParm;
1078
1079 font16->lfHeight = logfont->lfHeight;
1080 font16->lfWidth = logfont->lfWidth;
1081 font16->lfEscapement = logfont->lfEscapement;
1082 font16->lfOrientation = logfont->lfOrientation;
1083 font16->lfWeight = logfont->lfWeight;
1084 font16->lfItalic = logfont->lfItalic;
1085 font16->lfUnderline = logfont->lfUnderline;
1086 font16->lfStrikeOut = logfont->lfStrikeOut;
1087 font16->lfCharSet = logfont->lfCharSet;
1088 font16->lfOutPrecision = logfont->lfOutPrecision;
1089 font16->lfClipPrecision = logfont->lfClipPrecision;
1090 font16->lfQuality = logfont->lfQuality;
1091 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
1092 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName,
1093 LF_FACESIZE - 1, NULL, NULL );
1094 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
1095 memset( font16->lfFaceName + written, 0, LF_FACESIZE - written );
1096
1097 if (!metadc_write_record( metadc, mr, mr->rdSize * 2 ))
1098 return 0;
1099 return metadc_add_handle( metadc, font );
1100 }
1101
METADC_SelectFont(HDC hdc,HFONT hfont)1102 static HFONT METADC_SelectFont( HDC hdc, HFONT hfont )
1103 {
1104 struct metadc *metadc = get_metadc_ptr( hdc );
1105 LOGFONTW font;
1106 INT16 index;
1107 HFONT ret;
1108
1109 index = metadc_find_object( metadc, hfont );
1110 if (index < 0)
1111 {
1112 if (!GetObjectW( hfont, sizeof(font), &font ))
1113 return 0;
1114 index = metadc_create_font( metadc, hfont, &font );
1115 if( index < 0 )
1116 return 0;
1117 GDI_hdc_using_object( hfont, hdc );//, METADC_DeleteObject );
1118 }
1119 if (!metadc_select_object( hdc, index )) return 0;
1120 ret = metadc->font;
1121 metadc->font = hfont;
1122 return ret;
1123 }
1124
metadc_create_pen(struct metadc * metadc,HPEN pen,LOGPEN16 * logpen)1125 static UINT16 metadc_create_pen( struct metadc *metadc, HPEN pen, LOGPEN16 *logpen )
1126 {
1127 unsigned char buffer[FIELD_OFFSET(METARECORD, rdParm)
1128 + (sizeof(*logpen) / sizeof(WORD)) * RTL_FIELD_SIZE(METARECORD, rdParm)];
1129 METARECORD *mr = (METARECORD *)&buffer;
1130
1131 mr->rdSize = sizeof(buffer) / sizeof(WORD);
1132 mr->rdFunction = META_CREATEPENINDIRECT;
1133 memcpy( mr->rdParm, logpen, sizeof(*logpen) );
1134 if (!metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) )) return 0;
1135 return metadc_add_handle( metadc, pen );
1136 }
1137
METADC_SelectPen(HDC hdc,HPEN hpen)1138 static HPEN METADC_SelectPen( HDC hdc, HPEN hpen )
1139 {
1140 struct metadc *metadc = get_metadc_ptr( hdc );
1141 LOGPEN16 logpen;
1142 INT16 index;
1143 HPEN ret;
1144
1145 index = metadc_find_object( metadc, hpen );
1146 if (index < 0)
1147 {
1148 /* must be an extended pen */
1149 INT size = GetObjectW( hpen, 0, NULL );
1150
1151 if (!size) return 0;
1152
1153 if (size == sizeof(LOGPEN))
1154 {
1155 LOGPEN pen;
1156
1157 GetObjectW( hpen, sizeof(pen), &pen );
1158 logpen.lopnStyle = pen.lopnStyle;
1159 logpen.lopnWidth.x = pen.lopnWidth.x;
1160 logpen.lopnWidth.y = pen.lopnWidth.y;
1161 logpen.lopnColor = pen.lopnColor;
1162 }
1163 else /* must be an extended pen */
1164 {
1165 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
1166
1167 GetObjectW( hpen, size, elp );
1168 /* FIXME: add support for user style pens */
1169 logpen.lopnStyle = elp->elpPenStyle;
1170 logpen.lopnWidth.x = elp->elpWidth;
1171 logpen.lopnWidth.y = 0;
1172 logpen.lopnColor = elp->elpColor;
1173
1174 HeapFree( GetProcessHeap(), 0, elp );
1175 }
1176
1177 index = metadc_create_pen( metadc, hpen, &logpen );
1178 if( index < 0 )
1179 return 0;
1180 GDI_hdc_using_object( hpen, hdc );//, METADC_DeleteObject );
1181 }
1182
1183 if (!metadc_select_object( hdc, index )) return 0;
1184 ret = metadc->pen;
1185 metadc->pen = hpen;
1186 return ret;
1187 }
1188
metadc_create_palette(struct metadc * metadc,HPALETTE palette,LOGPALETTE * log_palette,int sizeofPalette)1189 static BOOL metadc_create_palette( struct metadc *metadc, HPALETTE palette,
1190 LOGPALETTE *log_palette, int sizeofPalette )
1191 {
1192 int index;
1193 BOOL ret;
1194 METARECORD *mr;
1195
1196 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
1197 if (!mr) return FALSE;
1198 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
1199 mr->rdFunction = META_CREATEPALETTE;
1200 memcpy(&(mr->rdParm), log_palette, sizeofPalette);
1201 if (!metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) ))
1202 {
1203 HeapFree(GetProcessHeap(), 0, mr);
1204 return FALSE;
1205 }
1206
1207 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
1208 mr->rdFunction = META_SELECTPALETTE;
1209
1210 if ((index = metadc_add_handle( metadc, palette )) == -1) ret = FALSE;
1211 else
1212 {
1213 mr->rdParm[0] = index;
1214 ret = metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) );
1215 }
1216 HeapFree( GetProcessHeap(), 0, mr );
1217 return ret;
1218 }
1219
METADC_SelectPalette(HDC hdc,HPALETTE palette)1220 BOOL METADC_SelectPalette( HDC hdc, HPALETTE palette )
1221 {
1222 struct metadc *metadc;
1223 PLOGPALETTE log_palette;
1224 WORD count = 0;
1225 BOOL ret;
1226 int size;
1227
1228 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
1229 GetObjectA( palette, sizeof(WORD), &count );
1230 if (!count) return 0;
1231
1232 size = sizeof(LOGPALETTE) + (count - 1) * sizeof(PALETTEENTRY);
1233 log_palette = HeapAlloc( GetProcessHeap(), 0, size );
1234 if (!log_palette) return 0;
1235
1236 log_palette->palVersion = 0x300;
1237 log_palette->palNumEntries = count;
1238
1239 GetPaletteEntries( palette, 0, count, log_palette->palPalEntry );
1240
1241 ret = metadc_create_palette( metadc, palette, log_palette, size );
1242
1243 HeapFree( GetProcessHeap(), 0, log_palette );
1244 return ret;
1245 }
1246
METADC_RealizePalette(HDC hdc)1247 BOOL METADC_RealizePalette( HDC hdc )
1248 {
1249 return metadc_param0( hdc, META_REALIZEPALETTE );
1250 }
1251
METADC_SelectObject(HDC hdc,HGDIOBJ obj)1252 HGDIOBJ METADC_SelectObject( HDC hdc, HGDIOBJ obj )
1253 {
1254 switch (GDI_HANDLE_GET_TYPE( obj ))
1255 {
1256 case GDILoObjType_LO_BRUSH_TYPE:
1257 return METADC_SelectBrush( hdc, obj );
1258 case GDILoObjType_LO_FONT_TYPE:
1259 return METADC_SelectFont( hdc, obj );
1260 case GDILoObjType_LO_PEN_TYPE:
1261 case GDILoObjType_LO_EXTPEN_TYPE:
1262 return METADC_SelectPen( hdc, obj );
1263 default:
1264 SetLastError( ERROR_INVALID_FUNCTION );
1265 return 0;
1266 }
1267 }
1268
METADC_ExtEscape(HDC hdc,INT escape,INT input_size,LPCSTR input,INT output_size,LPVOID output)1269 BOOL METADC_ExtEscape( HDC hdc, INT escape, INT input_size, LPCSTR input, INT output_size, LPVOID output )
1270 {
1271 METARECORD *mr;
1272 DWORD len;
1273 BOOL ret;
1274
1275 if (output_size) return FALSE; /* escapes that require output cannot work in metafiles */
1276
1277 len = sizeof(*mr) + sizeof(WORD) + ((input_size + 1) & ~1);
1278 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) return FALSE;
1279 mr->rdSize = len / sizeof(WORD);
1280 mr->rdFunction = META_ESCAPE;
1281 mr->rdParm[0] = escape;
1282 mr->rdParm[1] = input_size;
1283 memcpy( &mr->rdParm[2], input, input_size );
1284 ret = metadc_record( hdc, mr, len );
1285 HeapFree(GetProcessHeap(), 0, mr);
1286 return ret;
1287 }
1288
METADC_GetDeviceCaps(HDC hdc,INT cap)1289 INT METADC_GetDeviceCaps( HDC hdc, INT cap )
1290 {
1291 if (!get_metadc_ptr( hdc )) return 0;
1292
1293 switch(cap)
1294 {
1295 case TECHNOLOGY:
1296 return DT_METAFILE;
1297 case TEXTCAPS:
1298 return 0;
1299 default:
1300 TRACE(" unsupported capability %d, will return 0\n", cap );
1301 }
1302 return 0;
1303 }
1304
metadc_free(struct metadc * metadc)1305 static void metadc_free( struct metadc *metadc )
1306 {
1307 DWORD index;
1308
1309 CloseHandle( metadc->hFile );
1310 HeapFree( GetProcessHeap(), 0, metadc->mh );
1311 for(index = 0; index < metadc->handles_size; index++)
1312 if(metadc->handles[index])
1313 GDI_hdc_not_using_object( metadc->handles[index], metadc->hdc );
1314 HeapFree( GetProcessHeap(), 0, metadc->handles );
1315 HeapFree( GetProcessHeap(), 0, metadc );
1316 }
1317
METADC_DeleteDC(HDC hdc)1318 BOOL METADC_DeleteDC( HDC hdc )
1319 {
1320 struct metadc *metadc;
1321
1322 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
1323 if (!GdiDeleteClientObj( hdc )) return FALSE;
1324 metadc_free( metadc );
1325 return TRUE;
1326 }
1327
1328 /**********************************************************************
1329 * CreateMetaFileW (GDI32.@)
1330 *
1331 * Create a new DC and associate it with a metafile. Pass a filename
1332 * to create a disk-based metafile, NULL to create a memory metafile.
1333 */
CreateMetaFileW(const WCHAR * filename)1334 HDC WINAPI CreateMetaFileW( const WCHAR *filename )
1335 {
1336 struct metadc *metadc;
1337 HANDLE hdc;
1338
1339 TRACE( "%s\n", debugstr_w(filename) );
1340
1341 metadc = HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc) );
1342 if (!metadc)
1343 {
1344 return NULL;
1345 }
1346 if (!(metadc->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc->mh) )))
1347 {
1348 HeapFree( GetProcessHeap(), 0, metadc );
1349 return NULL;
1350 }
1351
1352 if (!(hdc = GdiCreateClientObj( metadc, GDILoObjType_LO_METADC16_TYPE )))
1353 {
1354 HeapFree( GetProcessHeap(), 0, metadc );
1355 return NULL;
1356 }
1357
1358 metadc->hdc = hdc;
1359
1360 metadc->handles = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1361 HANDLE_LIST_INC * sizeof(metadc->handles[0]) );
1362 metadc->handles_size = HANDLE_LIST_INC;
1363 metadc->cur_handles = 0;
1364
1365 metadc->hFile = 0;
1366
1367 metadc->mh->mtHeaderSize = sizeof(METAHEADER) / sizeof(WORD);
1368 metadc->mh->mtVersion = 0x0300;
1369 metadc->mh->mtSize = metadc->mh->mtHeaderSize;
1370 metadc->mh->mtNoObjects = 0;
1371 metadc->mh->mtMaxRecord = 0;
1372 metadc->mh->mtNoParameters = 0;
1373 metadc->mh->mtType = METAFILE_MEMORY;
1374
1375 metadc->pen = GetStockObject( BLACK_PEN );
1376 metadc->brush = GetStockObject( WHITE_BRUSH );
1377 metadc->font = GetStockObject( DEVICE_DEFAULT_FONT );
1378
1379 SetVirtualResolution( hdc, 0, 0, 0, 0);
1380
1381 if (filename) /* disk based metafile */
1382 {
1383 HANDLE file = CreateFileW( filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1384 if (file == INVALID_HANDLE_VALUE)
1385 {
1386 HeapFree( GetProcessHeap(), 0, metadc );
1387 GdiDeleteClientObj( hdc );
1388 return 0;
1389 }
1390 metadc->hFile = file;
1391 }
1392
1393 TRACE( "returning %p\n", hdc );
1394 return hdc;
1395 }
1396
1397 /**********************************************************************
1398 * CreateMetaFileA (GDI32.@)
1399 */
CreateMetaFileA(const char * filename)1400 HDC WINAPI CreateMetaFileA( const char *filename )
1401 {
1402 LPWSTR filenameW;
1403 DWORD len;
1404 HDC hdc;
1405
1406 if (!filename) return CreateMetaFileW( NULL );
1407
1408 len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
1409 filenameW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1410 MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len );
1411
1412 hdc = CreateMetaFileW( filenameW );
1413
1414 HeapFree( GetProcessHeap(), 0, filenameW );
1415 return hdc;
1416 }
1417
1418 /******************************************************************
1419 * CloseMetaFile (GDI32.@)
1420 *
1421 * Stop recording graphics operations in metafile associated with
1422 * hdc and retrieve metafile.
1423 */
CloseMetaFile(HDC hdc)1424 HMETAFILE WINAPI CloseMetaFile( HDC hdc )
1425 {
1426 struct metadc *metadc;
1427 DWORD bytes_written;
1428 HMETAFILE hmf;
1429
1430 TRACE( "(%p)\n", hdc );
1431
1432 if (!(metadc = get_metadc_ptr( hdc ))) return FALSE;
1433
1434 /* Construct the end of metafile record - this is documented
1435 * in SDK Knowledgebase Q99334.
1436 */
1437 if (!metadc_param0( hdc, META_EOF )) return FALSE;
1438 if (!GdiDeleteClientObj( hdc )) return FALSE;
1439
1440 if (metadc->hFile && !WriteFile( metadc->hFile, metadc->mh, metadc->mh->mtSize * sizeof(WORD),
1441 &bytes_written, NULL ))
1442 {
1443 metadc_free( metadc );
1444 return FALSE;
1445 }
1446
1447 /* Now allocate a global handle for the metafile */
1448 hmf = MF_Create_HMETAFILE( metadc->mh );
1449 if (hmf) metadc->mh = NULL; /* So it won't be deleted */
1450 metadc_free( metadc );
1451 return hmf;
1452 }
1453