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 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 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 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 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 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 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 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 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 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 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 201 BOOL METADC_SaveDC( HDC hdc ) 202 { 203 return metadc_param0( hdc, META_SAVEDC ); 204 } 205 206 BOOL METADC_RestoreDC( HDC hdc, INT level ) 207 { 208 return metadc_param1( hdc, META_RESTOREDC, level ); 209 } 210 211 BOOL METADC_SetTextAlign( HDC hdc, UINT align ) 212 { 213 return metadc_param2( hdc, META_SETTEXTALIGN, HIWORD(align), LOWORD(align) ); 214 } 215 216 BOOL METADC_SetBkMode( HDC hdc, INT mode ) 217 { 218 return metadc_param1( hdc, META_SETBKMODE, (WORD)mode ); 219 } 220 221 BOOL METADC_SetBkColor( HDC hdc, COLORREF color ) 222 { 223 return metadc_param2( hdc, META_SETBKCOLOR, HIWORD(color), LOWORD(color) ); 224 } 225 226 BOOL METADC_SetTextColor( HDC hdc, COLORREF color ) 227 { 228 return metadc_param2( hdc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color) ); 229 } 230 231 BOOL METADC_SetROP2( HDC hdc, INT rop ) 232 { 233 return metadc_param1( hdc, META_SETROP2, (WORD)rop ); 234 } 235 236 BOOL METADC_SetRelAbs( HDC hdc, INT mode ) 237 { 238 return metadc_param1( hdc, META_SETRELABS, (WORD)mode ); 239 } 240 241 BOOL METADC_SetPolyFillMode( HDC hdc, INT mode ) 242 { 243 return metadc_param1( hdc, META_SETPOLYFILLMODE, mode ); 244 } 245 246 BOOL METADC_SetStretchBltMode( HDC hdc, INT mode ) 247 { 248 return metadc_param1( hdc, META_SETSTRETCHBLTMODE, mode ); 249 } 250 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 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 261 BOOL METADC_OffsetClipRgn( HDC hdc, INT x, INT y ) 262 { 263 return metadc_param2( hdc, META_OFFSETCLIPRGN, x, y ); 264 } 265 266 BOOL METADC_SetLayout( HDC hdc, DWORD layout ) 267 { 268 return metadc_param2( hdc, META_SETLAYOUT, HIWORD(layout), LOWORD(layout) ); 269 } 270 271 BOOL METADC_SetMapMode( HDC hdc, INT mode ) 272 { 273 return metadc_param1( hdc, META_SETMAPMODE, mode ); 274 } 275 276 BOOL METADC_SetViewportExtEx( HDC hdc, INT x, INT y ) 277 { 278 return metadc_param2( hdc, META_SETVIEWPORTEXT, x, y ); 279 } 280 281 BOOL METADC_SetViewportOrgEx( HDC hdc, INT x, INT y ) 282 { 283 return metadc_param2( hdc, META_SETVIEWPORTORG, x, y ); 284 } 285 286 BOOL METADC_SetWindowExtEx( HDC hdc, INT x, INT y ) 287 { 288 return metadc_param2( hdc, META_SETWINDOWEXT, x, y ); 289 } 290 291 BOOL METADC_SetWindowOrgEx( HDC hdc, INT x, INT y ) 292 { 293 return metadc_param2( hdc, META_SETWINDOWORG, x, y ); 294 } 295 296 BOOL METADC_OffsetViewportOrgEx( HDC hdc, INT x, INT y ) 297 { 298 return metadc_param2( hdc, META_OFFSETVIEWPORTORG, x, y ); 299 } 300 301 BOOL METADC_OffsetWindowOrgEx( HDC hdc, INT x, INT y ) 302 { 303 return metadc_param2( hdc, META_OFFSETWINDOWORG, x, y ); 304 } 305 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 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 316 BOOL METADC_SetTextJustification( HDC hdc, INT extra, INT breaks ) 317 { 318 return metadc_param2( hdc, META_SETTEXTJUSTIFICATION, extra, breaks ); 319 } 320 321 BOOL METADC_SetTextCharacterExtra( HDC hdc, INT extra ) 322 { 323 return metadc_param1( hdc, META_SETTEXTCHAREXTRA, extra ); 324 } 325 326 BOOL METADC_SetMapperFlags( HDC hdc, DWORD flags ) 327 { 328 return metadc_param2( hdc, META_SETMAPPERFLAGS, HIWORD(flags), LOWORD(flags) ); 329 } 330 331 BOOL METADC_MoveTo( HDC hdc, INT x, INT y ) 332 { 333 return metadc_param2( hdc, META_MOVETO, x, y ); 334 } 335 336 BOOL METADC_LineTo( HDC hdc, INT x, INT y ) 337 { 338 return metadc_param2( hdc, META_LINETO, x, y ); 339 } 340 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1247 BOOL METADC_RealizePalette( HDC hdc ) 1248 { 1249 return metadc_param0( hdc, META_REALIZEPALETTE ); 1250 } 1251 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 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 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 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 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 */ 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 */ 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 */ 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