ReactOS 0.4.15-dev-7674-gc0b4db1
enhmetafile.c
Go to the documentation of this file.
1/*
2 * Enhanced metafile functions
3 * Copyright 1998 Douglas Ridgway
4 * 1999 Huw D M Davies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * NOTES:
21 *
22 * The enhanced format consists of the following elements:
23 *
24 * A header
25 * A table of handles to GDI objects
26 * An array of metafile records
27 * A private palette
28 *
29 *
30 * The standard format consists of a header and an array of metafile records.
31 *
32 */
33
34#include "config.h"
35#include "wine/port.h"
36
37#include <stdarg.h>
38#include <stdlib.h>
39#include <string.h>
40#include <assert.h>
41#include "windef.h"
42#include "winbase.h"
43#include "wingdi.h"
44#include "winnls.h"
45#include "winerror.h"
46#include "gdi_private.h"
47#include "wine/debug.h"
48
50
51
54{
55 0, 0, &enhmetafile_cs,
57 0, 0, { (DWORD_PTR)(__FILE__ ": enhmetafile_cs") }
58};
59static CRITICAL_SECTION enhmetafile_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
60
61typedef struct
62{
64 BOOL on_disk; /* true if metafile is on disk */
66
67static const struct emr_name {
69 const char *name;
70} emr_names[] = {
71#define X(p) {p, #p}
85X(EMR_EOF),
116X(EMR_ARC),
117X(EMR_CHORD),
118X(EMR_PIE),
126X(EMR_ARCTO),
175X(EMR_DRAWESCAPE),
176X(EMR_EXTESCAPE),
177X(EMR_STARTDOC),
178X(EMR_SMALLTEXTOUT),
179X(EMR_FORCEUFIMAPPING),
180X(EMR_NAMEDESCAPE),
181X(EMR_COLORCORRECTPALETTE),
182X(EMR_SETICMPROFILEA),
183X(EMR_SETICMPROFILEW),
184X(EMR_ALPHABLEND),
185X(EMR_SETLAYOUT),
186X(EMR_TRANSPARENTBLT),
187X(EMR_RESERVED_117),
188X(EMR_GRADIENTFILL),
190X(EMR_SETTEXTJUSTIFICATION),
191X(EMR_COLORMATCHTOTARGETW),
192X(EMR_CREATECOLORSPACEW)
193#undef X
195
196/****************************************************************************
197 * get_emr_name
198 */
199static const char *get_emr_name(DWORD type)
200{
201 unsigned int i;
202 for(i = 0; i < sizeof(emr_names) / sizeof(emr_names[0]); i++)
203 if(type == emr_names[i].type) return emr_names[i].name;
204 TRACE("Unknown record type %d\n", type);
205 return NULL;
206}
207
208/***********************************************************************
209 * is_dib_monochrome
210 *
211 * Returns whether a DIB can be converted to a monochrome DDB.
212 *
213 * A DIB can be converted if its color table contains only black and
214 * white. Black must be the first color in the color table.
215 *
216 * Note : If the first color in the color table is white followed by
217 * black, we can't convert it to a monochrome DDB with
218 * SetDIBits, because black and white would be inverted.
219 */
220static inline BOOL is_dib_monochrome( const BITMAPINFO* info )
221{
222 if (info->bmiHeader.biBitCount != 1) return FALSE;
223
224 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
225 {
226 const RGBTRIPLE *rgb = ((const BITMAPCOREINFO *) info)->bmciColors;
227
228 /* Check if the first color is black */
229 if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
230 {
231 rgb++;
232 /* Check if the second color is white */
233 return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
234 && (rgb->rgbtBlue == 0xff));
235 }
236 else return FALSE;
237 }
238 else /* assume BITMAPINFOHEADER */
239 {
240 const RGBQUAD *rgb = info->bmiColors;
241
242 /* Check if the first color is black */
243 if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) &&
244 (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0))
245 {
246 rgb++;
247
248 /* Check if the second color is white */
249 return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff)
250 && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0));
251 }
252 else return FALSE;
253 }
254}
255
256/****************************************************************************
257 * EMF_Create_HENHMETAFILE
258 */
259HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, DWORD filesize, BOOL on_disk )
260{
261 HENHMETAFILE hmf;
262 ENHMETAFILEOBJ *metaObj;
263
264 if (emh->iType != EMR_HEADER)
265 {
267 return 0;
268 }
269 if (emh->dSignature != ENHMETA_SIGNATURE ||
270 (emh->nBytes & 3)) /* refuse to load unaligned EMF as Windows does */
271 {
272 WARN("Invalid emf header type 0x%08x sig 0x%08x.\n",
273 emh->iType, emh->dSignature);
274 return 0;
275 }
276 if (filesize < emh->nBytes)
277 {
278 WARN("File truncated (got %u bytes, header says %u)\n", emh->nBytes, filesize);
279 return 0;
280 }
281
282 if (!(metaObj = HeapAlloc( GetProcessHeap(), 0, sizeof(*metaObj) ))) return 0;
283
284 metaObj->emh = emh;
285 metaObj->on_disk = on_disk;
286
287 if (!(hmf = alloc_gdi_handle( metaObj, OBJ_ENHMETAFILE, NULL )))
288 HeapFree( GetProcessHeap(), 0, metaObj );
289 return hmf;
290}
291
292/****************************************************************************
293 * EMF_Delete_HENHMETAFILE
294 */
295static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf )
296{
297 ENHMETAFILEOBJ *metaObj;
298 BOOL Ret = FALSE;
299
301 metaObj = free_gdi_handle( hmf );
302 if(metaObj)
303 {
304 if(metaObj->on_disk)
305 UnmapViewOfFile( metaObj->emh );
306 else
307 HeapFree( GetProcessHeap(), 0, metaObj->emh );
308 HeapFree( GetProcessHeap(), 0, metaObj );
309 Ret = TRUE;
310 }
312 return Ret;
313}
314
315/******************************************************************
316 * EMF_GetEnhMetaHeader
317 *
318 * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE
319 */
320static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf )
321{
323 ENHMETAFILEOBJ *metaObj;
324
326 metaObj = GDI_GetObjPtr( hmf, OBJ_ENHMETAFILE );
327 TRACE("hmf %p -> enhmetaObj %p\n", hmf, metaObj);
328 if (metaObj)
329 {
330 ret = metaObj->emh;
331 GDI_ReleaseObj( hmf );
332 }
334 return ret;
335}
336
337/*****************************************************************************
338 * EMF_GetEnhMetaFile
339 *
340 */
341static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile )
342{
343 ENHMETAHEADER *emh;
344 HANDLE hMapping;
345 HENHMETAFILE hemf;
346 DWORD filesize;
347
348 filesize = GetFileSize( hFile, NULL );
349
350 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
351 emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
352 CloseHandle( hMapping );
353
354 if (!emh) return 0;
355
356 hemf = EMF_Create_HENHMETAFILE( emh, filesize, TRUE );
357 if (!hemf)
358 UnmapViewOfFile( emh );
359 return hemf;
360}
361
362
363/*****************************************************************************
364 * GetEnhMetaFileA (GDI32.@)
365 *
366 *
367 */
369 LPCSTR lpszMetaFile /* [in] filename of enhanced metafile */
370 )
371{
372 HENHMETAFILE hmf;
374
375 hFile = CreateFileA(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
376 OPEN_EXISTING, 0, 0);
378 WARN("could not open %s\n", lpszMetaFile);
379 return 0;
380 }
381 hmf = EMF_GetEnhMetaFile( hFile );
383 return hmf;
384}
385
386/*****************************************************************************
387 * GetEnhMetaFileW (GDI32.@)
388 */
390 LPCWSTR lpszMetaFile) /* [in] filename of enhanced metafile */
391{
392 HENHMETAFILE hmf;
394
395 hFile = CreateFileW(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
396 OPEN_EXISTING, 0, 0);
398 WARN("could not open %s\n", debugstr_w(lpszMetaFile));
399 return 0;
400 }
401 hmf = EMF_GetEnhMetaFile( hFile );
403 return hmf;
404}
405
406/*****************************************************************************
407 * GetEnhMetaFileHeader (GDI32.@)
408 *
409 * Retrieves the record containing the header for the specified
410 * enhanced-format metafile.
411 *
412 * RETURNS
413 * If buf is NULL, returns the size of buffer required.
414 * Otherwise, copy up to bufsize bytes of enhanced metafile header into
415 * buf.
416 */
418 HENHMETAFILE hmf, /* [in] enhanced metafile */
419 UINT bufsize, /* [in] size of buffer */
420 LPENHMETAHEADER buf /* [out] buffer */
421 )
422{
423 LPENHMETAHEADER emh;
424 UINT size;
425
426 emh = EMF_GetEnhMetaHeader(hmf);
427 if(!emh) return FALSE;
428 size = emh->nSize;
429 if (!buf) return size;
430 size = min(size, bufsize);
431 memmove(buf, emh, size);
432 return size;
433}
434
435
436/*****************************************************************************
437 * GetEnhMetaFileDescriptionA (GDI32.@)
438 *
439 * See GetEnhMetaFileDescriptionW.
440 */
442 HENHMETAFILE hmf, /* [in] enhanced metafile */
443 UINT size, /* [in] size of buf */
444 LPSTR buf /* [out] buffer to receive description */
445 )
446{
448 DWORD len;
449 WCHAR *descrW;
450
451 if(!emh) return FALSE;
452 if(emh->nDescription == 0 || emh->offDescription == 0) return 0;
453 descrW = (WCHAR *) ((char *) emh + emh->offDescription);
454 len = WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, NULL, 0, NULL, NULL );
455
456 if (!buf || !size ) return len;
457
458 len = min( size, len );
459 WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, buf, len, NULL, NULL );
460 return len;
461}
462
463/*****************************************************************************
464 * GetEnhMetaFileDescriptionW (GDI32.@)
465 *
466 * Copies the description string of an enhanced metafile into a buffer
467 * _buf_.
468 *
469 * RETURNS
470 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
471 * number of characters copied.
472 */
474 HENHMETAFILE hmf, /* [in] enhanced metafile */
475 UINT size, /* [in] size of buf */
476 LPWSTR buf /* [out] buffer to receive description */
477 )
478{
480
481 if(!emh) return FALSE;
482 if(emh->nDescription == 0 || emh->offDescription == 0) return 0;
483 if (!buf || !size ) return emh->nDescription;
484
485 memmove(buf, (char *) emh + emh->offDescription, min(size,emh->nDescription)*sizeof(WCHAR));
486 return min(size, emh->nDescription);
487}
488
489/****************************************************************************
490 * SetEnhMetaFileBits (GDI32.@)
491 *
492 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
493 */
495{
497 HENHMETAFILE hmf;
498 memmove(emh, buf, bufsize);
500 if (!hmf)
501 HeapFree( GetProcessHeap(), 0, emh );
502 return hmf;
503}
504
505/*****************************************************************************
506 * GetEnhMetaFileBits (GDI32.@)
507 *
508 */
510 HENHMETAFILE hmf,
512 LPBYTE buf
513)
514{
516 UINT size;
517
518 if(!emh) return 0;
519
520 size = emh->nBytes;
521 if( buf == NULL ) return size;
522
523 size = min( size, bufsize );
524 memmove(buf, emh, size);
525 return size;
526}
527
528typedef struct EMF_dc_state
529{
542
543typedef struct enum_emh_data
544{
550
551#define ENUM_GET_PRIVATE_DATA(ht) \
552 ((enum_emh_data*)(((unsigned char*)(ht))-sizeof (enum_emh_data)))
553
554#define WIDTH(rect) ( (rect).right - (rect).left )
555#define HEIGHT(rect) ( (rect).bottom - (rect).top )
556
557#define IS_WIN9X() (GetVersion()&0x80000000)
558
560{
561 XFORM mapping_mode_trans, final_trans;
562 double scaleX, scaleY;
563
564 scaleX = (double)info->state.vportExtX / (double)info->state.wndExtX;
565 scaleY = (double)info->state.vportExtY / (double)info->state.wndExtY;
566 mapping_mode_trans.eM11 = scaleX;
567 mapping_mode_trans.eM12 = 0.0;
568 mapping_mode_trans.eM21 = 0.0;
569 mapping_mode_trans.eM22 = scaleY;
570 mapping_mode_trans.eDx = (double)info->state.vportOrgX - scaleX * (double)info->state.wndOrgX;
571 mapping_mode_trans.eDy = (double)info->state.vportOrgY - scaleY * (double)info->state.wndOrgY;
572
573 CombineTransform(&final_trans, &info->state.world_transform, &mapping_mode_trans);
574 CombineTransform(&final_trans, &final_trans, &info->init_transform);
575
576 if (!SetWorldTransform(hdc, &final_trans))
577 {
578 ERR("World transform failed!\n");
579 }
580}
581
583{
584 if (abs(level) > info->save_level || level == 0) return;
585
586 if (level < 0) level = info->save_level + level + 1;
587
588 while (info->save_level >= level)
589 {
590 EMF_dc_state *state = info->saved_state;
591 info->saved_state = state->next;
592 state->next = NULL;
593 if (--info->save_level < level)
594 info->state = *state;
596 }
597}
598
600{
601 EMF_dc_state *state = HeapAlloc( GetProcessHeap(), 0, sizeof(*state));
602 if (state)
603 {
604 *state = info->state;
605 state->next = info->saved_state;
606 info->saved_state = state;
607 info->save_level++;
608 TRACE("save_level %d\n", info->save_level);
609 }
610}
611
613{
614 INT horzSize = GetDeviceCaps( hdc, HORZSIZE );
615 INT vertSize = GetDeviceCaps( hdc, VERTSIZE );
616 INT horzRes = GetDeviceCaps( hdc, HORZRES );
617 INT vertRes = GetDeviceCaps( hdc, VERTRES );
618
619 TRACE("%d\n", info->state.mode);
620
621 switch(info->state.mode)
622 {
623 case MM_TEXT:
624 info->state.wndExtX = 1;
625 info->state.wndExtY = 1;
626 info->state.vportExtX = 1;
627 info->state.vportExtY = 1;
628 break;
629 case MM_LOMETRIC:
630 case MM_ISOTROPIC:
631 info->state.wndExtX = horzSize * 10;
632 info->state.wndExtY = vertSize * 10;
633 info->state.vportExtX = horzRes;
634 info->state.vportExtY = -vertRes;
635 break;
636 case MM_HIMETRIC:
637 info->state.wndExtX = horzSize * 100;
638 info->state.wndExtY = vertSize * 100;
639 info->state.vportExtX = horzRes;
640 info->state.vportExtY = -vertRes;
641 break;
642 case MM_LOENGLISH:
643 info->state.wndExtX = MulDiv(1000, horzSize, 254);
644 info->state.wndExtY = MulDiv(1000, vertSize, 254);
645 info->state.vportExtX = horzRes;
646 info->state.vportExtY = -vertRes;
647 break;
648 case MM_HIENGLISH:
649 info->state.wndExtX = MulDiv(10000, horzSize, 254);
650 info->state.wndExtY = MulDiv(10000, vertSize, 254);
651 info->state.vportExtX = horzRes;
652 info->state.vportExtY = -vertRes;
653 break;
654 case MM_TWIPS:
655 info->state.wndExtX = MulDiv(14400, horzSize, 254);
656 info->state.wndExtY = MulDiv(14400, vertSize, 254);
657 info->state.vportExtX = horzRes;
658 info->state.vportExtY = -vertRes;
659 break;
660 case MM_ANISOTROPIC:
661 break;
662 default:
663 return;
664 }
665}
666
667/***********************************************************************
668 * EMF_FixIsotropic
669 *
670 * Fix viewport extensions for isotropic mode.
671 */
672
674{
675 double xdim = fabs((double)info->state.vportExtX * GetDeviceCaps( hdc, HORZSIZE ) /
676 (GetDeviceCaps( hdc, HORZRES ) * info->state.wndExtX));
677 double ydim = fabs((double)info->state.vportExtY * GetDeviceCaps( hdc, VERTSIZE ) /
678 (GetDeviceCaps( hdc, VERTRES ) * info->state.wndExtY));
679
680 if (xdim > ydim)
681 {
682 INT mincx = (info->state.vportExtX >= 0) ? 1 : -1;
683 info->state.vportExtX = floor(info->state.vportExtX * ydim / xdim + 0.5);
684 if (!info->state.vportExtX) info->state.vportExtX = mincx;
685 }
686 else
687 {
688 INT mincy = (info->state.vportExtY >= 0) ? 1 : -1;
689 info->state.vportExtY = floor(info->state.vportExtY * xdim / ydim + 0.5);
690 if (!info->state.vportExtY) info->state.vportExtY = mincy;
691 }
692}
693
694/*****************************************************************************
695 * emr_produces_output
696 *
697 * Returns TRUE if the record type writes something to the dc. Used by
698 * PlayEnhMetaFileRecord to determine whether it needs to update the
699 * dc's xform when in win9x mode.
700 *
701 * FIXME: need to test which records should be here.
702 */
704{
705 switch(type) {
706 case EMR_POLYBEZIER:
707 case EMR_POLYGON:
708 case EMR_POLYLINE:
709 case EMR_POLYBEZIERTO:
710 case EMR_POLYLINETO:
711 case EMR_POLYPOLYLINE:
712 case EMR_POLYPOLYGON:
713 case EMR_SETPIXELV:
714 case EMR_MOVETOEX:
717 case EMR_SELECTOBJECT:
718 case EMR_ANGLEARC:
719 case EMR_ELLIPSE:
720 case EMR_RECTANGLE:
721 case EMR_ROUNDRECT:
722 case EMR_ARC:
723 case EMR_CHORD:
724 case EMR_PIE:
725 case EMR_EXTFLOODFILL:
726 case EMR_LINETO:
727 case EMR_ARCTO:
728 case EMR_POLYDRAW:
729 case EMR_GDICOMMENT:
730 case EMR_FILLRGN:
731 case EMR_FRAMERGN:
732 case EMR_INVERTRGN:
733 case EMR_PAINTRGN:
734 case EMR_BITBLT:
735 case EMR_STRETCHBLT:
736 case EMR_MASKBLT:
737 case EMR_PLGBLT:
740 case EMR_EXTTEXTOUTA:
741 case EMR_EXTTEXTOUTW:
742 case EMR_POLYBEZIER16:
743 case EMR_POLYGON16:
744 case EMR_POLYLINE16:
746 case EMR_POLYLINETO16:
749 case EMR_POLYDRAW16:
750 case EMR_POLYTEXTOUTA:
751 case EMR_POLYTEXTOUTW:
752 case EMR_SMALLTEXTOUT:
753 case EMR_ALPHABLEND:
754 case EMR_TRANSPARENTBLT:
755 return TRUE;
756 default:
757 return FALSE;
758 }
759}
760
761
762/*****************************************************************************
763 * PlayEnhMetaFileRecord (GDI32.@)
764 *
765 * Render a single enhanced metafile record in the device context hdc.
766 *
767 * RETURNS
768 * TRUE (non zero) on success, FALSE on error.
769 * BUGS
770 * Many unimplemented records.
771 * No error handling on record play failures (ie checking return codes)
772 *
773 * NOTES
774 * WinNT actually updates the current world transform in this function
775 * whereas Win9x does not.
776 */
778 HDC hdc, /* [in] device context in which to render EMF record */
779 LPHANDLETABLE handletable, /* [in] array of handles to be used in rendering record */
780 const ENHMETARECORD *mr, /* [in] EMF record to render */
781 UINT handles /* [in] size of handle array */
782 )
783{
784 int type;
785 RECT tmprc;
787
788 TRACE("hdc = %p, handletable = %p, record = %p, numHandles = %d\n",
789 hdc, handletable, mr, handles);
790 if (!mr) return FALSE;
791
792 type = mr->iType;
793
794 TRACE("record %s\n", get_emr_name(type));
795 switch(type)
796 {
797 case EMR_HEADER:
798 break;
799 case EMR_EOF:
800 break;
801 case EMR_GDICOMMENT:
802 {
803 const EMRGDICOMMENT *lpGdiComment = (const EMRGDICOMMENT *)mr;
804 /* In an enhanced metafile, there can be both public and private GDI comments */
805 GdiComment( hdc, lpGdiComment->cbData, lpGdiComment->Data );
806 break;
807 }
808 case EMR_SETMAPMODE:
809 {
810 const EMRSETMAPMODE *pSetMapMode = (const EMRSETMAPMODE *)mr;
811
812 if (info->state.mode == pSetMapMode->iMode &&
813 (info->state.mode == MM_ISOTROPIC || info->state.mode == MM_ANISOTROPIC))
814 break;
815 info->state.mode = pSetMapMode->iMode;
817
818 if (!IS_WIN9X())
820
821 break;
822 }
823 case EMR_SETBKMODE:
824 {
825 const EMRSETBKMODE *pSetBkMode = (const EMRSETBKMODE *)mr;
826 SetBkMode(hdc, pSetBkMode->iMode);
827 break;
828 }
829 case EMR_SETBKCOLOR:
830 {
831 const EMRSETBKCOLOR *pSetBkColor = (const EMRSETBKCOLOR *)mr;
832 SetBkColor(hdc, pSetBkColor->crColor);
833 break;
834 }
836 {
837 const EMRSETPOLYFILLMODE *pSetPolyFillMode = (const EMRSETPOLYFILLMODE *)mr;
838 SetPolyFillMode(hdc, pSetPolyFillMode->iMode);
839 break;
840 }
841 case EMR_SETROP2:
842 {
843 const EMRSETROP2 *pSetROP2 = (const EMRSETROP2 *)mr;
844 SetROP2(hdc, pSetROP2->iMode);
845 break;
846 }
848 {
849 const EMRSETSTRETCHBLTMODE *pSetStretchBltMode = (const EMRSETSTRETCHBLTMODE *)mr;
850 SetStretchBltMode(hdc, pSetStretchBltMode->iMode);
851 break;
852 }
853 case EMR_SETTEXTALIGN:
854 {
855 const EMRSETTEXTALIGN *pSetTextAlign = (const EMRSETTEXTALIGN *)mr;
856 SetTextAlign(hdc, pSetTextAlign->iMode);
857 break;
858 }
859 case EMR_SETTEXTCOLOR:
860 {
861 const EMRSETTEXTCOLOR *pSetTextColor = (const EMRSETTEXTCOLOR *)mr;
862 SetTextColor(hdc, pSetTextColor->crColor);
863 break;
864 }
865 case EMR_SAVEDC:
866 {
867 if (SaveDC( hdc ))
868 EMF_SaveDC( info );
869 break;
870 }
871 case EMR_RESTOREDC:
872 {
873 const EMRRESTOREDC *pRestoreDC = (const EMRRESTOREDC *)mr;
874 TRACE("EMR_RESTORE: %d\n", pRestoreDC->iRelative);
875 if (RestoreDC( hdc, pRestoreDC->iRelative ))
876 EMF_RestoreDC( info, pRestoreDC->iRelative );
877 break;
878 }
880 {
881 const EMRINTERSECTCLIPRECT *pClipRect = (const EMRINTERSECTCLIPRECT *)mr;
882 TRACE("EMR_INTERSECTCLIPRECT: rect %d,%d - %d, %d\n",
883 pClipRect->rclClip.left, pClipRect->rclClip.top,
884 pClipRect->rclClip.right, pClipRect->rclClip.bottom);
885 IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top,
886 pClipRect->rclClip.right, pClipRect->rclClip.bottom);
887 break;
888 }
889 case EMR_SELECTOBJECT:
890 {
891 const EMRSELECTOBJECT *pSelectObject = (const EMRSELECTOBJECT *)mr;
892 if( pSelectObject->ihObject & 0x80000000 ) {
893 /* High order bit is set - it's a stock object
894 * Strip the high bit to get the index.
895 * See MSDN article Q142319
896 */
897 SelectObject( hdc, GetStockObject( pSelectObject->ihObject &
898 0x7fffffff ) );
899 } else {
900 /* High order bit wasn't set - not a stock object
901 */
903 (handletable->objectHandle)[pSelectObject->ihObject] );
904 }
905 break;
906 }
907 case EMR_DELETEOBJECT:
908 {
909 const EMRDELETEOBJECT *pDeleteObject = (const EMRDELETEOBJECT *)mr;
910 DeleteObject( (handletable->objectHandle)[pDeleteObject->ihObject]);
911 (handletable->objectHandle)[pDeleteObject->ihObject] = 0;
912 break;
913 }
915 {
916 const EMRSETWINDOWORGEX *pSetWindowOrgEx = (const EMRSETWINDOWORGEX *)mr;
917
918 info->state.wndOrgX = pSetWindowOrgEx->ptlOrigin.x;
919 info->state.wndOrgY = pSetWindowOrgEx->ptlOrigin.y;
920
921 TRACE("SetWindowOrgEx: %d,%d\n", info->state.wndOrgX, info->state.wndOrgY);
922
923 if (!IS_WIN9X())
925
926 break;
927 }
929 {
930 const EMRSETWINDOWEXTEX *pSetWindowExtEx = (const EMRSETWINDOWEXTEX *)mr;
931
932 if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
933 break;
934 info->state.wndExtX = pSetWindowExtEx->szlExtent.cx;
935 info->state.wndExtY = pSetWindowExtEx->szlExtent.cy;
936 if (info->state.mode == MM_ISOTROPIC)
938
939 TRACE("SetWindowExtEx: %d,%d\n",info->state.wndExtX, info->state.wndExtY);
940
941 if (!IS_WIN9X())
943
944 break;
945 }
947 {
948 const EMRSETVIEWPORTORGEX *pSetViewportOrgEx = (const EMRSETVIEWPORTORGEX *)mr;
949
950 info->state.vportOrgX = pSetViewportOrgEx->ptlOrigin.x;
951 info->state.vportOrgY = pSetViewportOrgEx->ptlOrigin.y;
952 TRACE("SetViewportOrgEx: %d,%d\n", info->state.vportOrgX, info->state.vportOrgY);
953
954 if (!IS_WIN9X())
956
957 break;
958 }
960 {
961 const EMRSETVIEWPORTEXTEX *pSetViewportExtEx = (const EMRSETVIEWPORTEXTEX *)mr;
962
963 if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
964 break;
965 info->state.vportExtX = pSetViewportExtEx->szlExtent.cx;
966 info->state.vportExtY = pSetViewportExtEx->szlExtent.cy;
967 if (info->state.mode == MM_ISOTROPIC)
969 TRACE("SetViewportExtEx: %d,%d\n", info->state.vportExtX, info->state.vportExtY);
970
971 if (!IS_WIN9X())
973
974 break;
975 }
976 case EMR_CREATEPEN:
977 {
978 const EMRCREATEPEN *pCreatePen = (const EMRCREATEPEN *)mr;
979 (handletable->objectHandle)[pCreatePen->ihPen] =
980 CreatePenIndirect(&pCreatePen->lopn);
981 break;
982 }
983 case EMR_EXTCREATEPEN:
984 {
985 const EMREXTCREATEPEN *pPen = (const EMREXTCREATEPEN *)mr;
986 LOGBRUSH lb;
987 lb.lbStyle = pPen->elp.elpBrushStyle;
988 lb.lbColor = pPen->elp.elpColor;
989 lb.lbHatch = pPen->elp.elpHatch;
990
991 if(pPen->offBmi || pPen->offBits)
992 FIXME("EMR_EXTCREATEPEN: Need to copy brush bitmap\n");
993
994 (handletable->objectHandle)[pPen->ihPen] =
995 ExtCreatePen(pPen->elp.elpPenStyle, pPen->elp.elpWidth, &lb,
996 pPen->elp.elpNumEntries, pPen->elp.elpNumEntries ? pPen->elp.elpStyleEntry : NULL);
997 break;
998 }
1000 {
1001 const EMRCREATEBRUSHINDIRECT *pBrush = (const EMRCREATEBRUSHINDIRECT *)mr;
1002 LOGBRUSH brush;
1003 brush.lbStyle = pBrush->lb.lbStyle;
1004 brush.lbColor = pBrush->lb.lbColor;
1005 brush.lbHatch = pBrush->lb.lbHatch;
1006 (handletable->objectHandle)[pBrush->ihBrush] = CreateBrushIndirect(&brush);
1007 break;
1008 }
1010 {
1011 const EMREXTCREATEFONTINDIRECTW *pFont = (const EMREXTCREATEFONTINDIRECTW *)mr;
1012 (handletable->objectHandle)[pFont->ihFont] =
1014 break;
1015 }
1016 case EMR_MOVETOEX:
1017 {
1018 const EMRMOVETOEX *pMoveToEx = (const EMRMOVETOEX *)mr;
1019 MoveToEx(hdc, pMoveToEx->ptl.x, pMoveToEx->ptl.y, NULL);
1020 break;
1021 }
1022 case EMR_LINETO:
1023 {
1024 const EMRLINETO *pLineTo = (const EMRLINETO *)mr;
1025 LineTo(hdc, pLineTo->ptl.x, pLineTo->ptl.y);
1026 break;
1027 }
1028 case EMR_RECTANGLE:
1029 {
1030 const EMRRECTANGLE *pRect = (const EMRRECTANGLE *)mr;
1031 Rectangle(hdc, pRect->rclBox.left, pRect->rclBox.top,
1032 pRect->rclBox.right, pRect->rclBox.bottom);
1033 break;
1034 }
1035 case EMR_ELLIPSE:
1036 {
1037 const EMRELLIPSE *pEllipse = (const EMRELLIPSE *)mr;
1038 Ellipse(hdc, pEllipse->rclBox.left, pEllipse->rclBox.top,
1039 pEllipse->rclBox.right, pEllipse->rclBox.bottom);
1040 break;
1041 }
1042 case EMR_POLYGON16:
1043 {
1044 const EMRPOLYGON16 *pPoly = (const EMRPOLYGON16 *)mr;
1045 /* Shouldn't use Polygon16 since pPoly->cpts is DWORD */
1046 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
1047 pPoly->cpts * sizeof(POINT) );
1048 DWORD i;
1049 for(i = 0; i < pPoly->cpts; i++)
1050 {
1051 pts[i].x = pPoly->apts[i].x;
1052 pts[i].y = pPoly->apts[i].y;
1053 }
1054 Polygon(hdc, pts, pPoly->cpts);
1055 HeapFree( GetProcessHeap(), 0, pts );
1056 break;
1057 }
1058 case EMR_POLYLINE16:
1059 {
1060 const EMRPOLYLINE16 *pPoly = (const EMRPOLYLINE16 *)mr;
1061 /* Shouldn't use Polyline16 since pPoly->cpts is DWORD */
1062 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
1063 pPoly->cpts * sizeof(POINT) );
1064 DWORD i;
1065 for(i = 0; i < pPoly->cpts; i++)
1066 {
1067 pts[i].x = pPoly->apts[i].x;
1068 pts[i].y = pPoly->apts[i].y;
1069 }
1070 Polyline(hdc, pts, pPoly->cpts);
1071 HeapFree( GetProcessHeap(), 0, pts );
1072 break;
1073 }
1074 case EMR_POLYLINETO16:
1075 {
1076 const EMRPOLYLINETO16 *pPoly = (const EMRPOLYLINETO16 *)mr;
1077 /* Shouldn't use PolylineTo16 since pPoly->cpts is DWORD */
1078 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
1079 pPoly->cpts * sizeof(POINT) );
1080 DWORD i;
1081 for(i = 0; i < pPoly->cpts; i++)
1082 {
1083 pts[i].x = pPoly->apts[i].x;
1084 pts[i].y = pPoly->apts[i].y;
1085 }
1086 PolylineTo(hdc, pts, pPoly->cpts);
1087 HeapFree( GetProcessHeap(), 0, pts );
1088 break;
1089 }
1090 case EMR_POLYBEZIER16:
1091 {
1092 const EMRPOLYBEZIER16 *pPoly = (const EMRPOLYBEZIER16 *)mr;
1093 /* Shouldn't use PolyBezier16 since pPoly->cpts is DWORD */
1094 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
1095 pPoly->cpts * sizeof(POINT) );
1096 DWORD i;
1097 for(i = 0; i < pPoly->cpts; i++)
1098 {
1099 pts[i].x = pPoly->apts[i].x;
1100 pts[i].y = pPoly->apts[i].y;
1101 }
1102 PolyBezier(hdc, pts, pPoly->cpts);
1103 HeapFree( GetProcessHeap(), 0, pts );
1104 break;
1105 }
1106 case EMR_POLYBEZIERTO16:
1107 {
1108 const EMRPOLYBEZIERTO16 *pPoly = (const EMRPOLYBEZIERTO16 *)mr;
1109 /* Shouldn't use PolyBezierTo16 since pPoly->cpts is DWORD */
1110 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
1111 pPoly->cpts * sizeof(POINT) );
1112 DWORD i;
1113 for(i = 0; i < pPoly->cpts; i++)
1114 {
1115 pts[i].x = pPoly->apts[i].x;
1116 pts[i].y = pPoly->apts[i].y;
1117 }
1118 PolyBezierTo(hdc, pts, pPoly->cpts);
1119 HeapFree( GetProcessHeap(), 0, pts );
1120 break;
1121 }
1122 case EMR_POLYPOLYGON16:
1123 {
1124 const EMRPOLYPOLYGON16 *pPolyPoly = (const EMRPOLYPOLYGON16 *)mr;
1125 /* NB POINTS array doesn't start at pPolyPoly->apts it's actually
1126 pPolyPoly->aPolyCounts + pPolyPoly->nPolys */
1127
1128 const POINTS *pts = (const POINTS *)(pPolyPoly->aPolyCounts + pPolyPoly->nPolys);
1129 POINT *pt = HeapAlloc( GetProcessHeap(), 0, pPolyPoly->cpts * sizeof(POINT) );
1130 DWORD i;
1131 for(i = 0; i < pPolyPoly->cpts; i++)
1132 {
1133 pt[i].x = pts[i].x;
1134 pt[i].y = pts[i].y;
1135 }
1136 PolyPolygon(hdc, pt, (const INT*)pPolyPoly->aPolyCounts, pPolyPoly->nPolys);
1137 HeapFree( GetProcessHeap(), 0, pt );
1138 break;
1139 }
1140 case EMR_POLYPOLYLINE16:
1141 {
1142 const EMRPOLYPOLYLINE16 *pPolyPoly = (const EMRPOLYPOLYLINE16 *)mr;
1143 /* NB POINTS array doesn't start at pPolyPoly->apts it's actually
1144 pPolyPoly->aPolyCounts + pPolyPoly->nPolys */
1145
1146 const POINTS *pts = (const POINTS *)(pPolyPoly->aPolyCounts + pPolyPoly->nPolys);
1147 POINT *pt = HeapAlloc( GetProcessHeap(), 0, pPolyPoly->cpts * sizeof(POINT) );
1148 DWORD i;
1149 for(i = 0; i < pPolyPoly->cpts; i++)
1150 {
1151 pt[i].x = pts[i].x;
1152 pt[i].y = pts[i].y;
1153 }
1154 PolyPolyline(hdc, pt, pPolyPoly->aPolyCounts, pPolyPoly->nPolys);
1155 HeapFree( GetProcessHeap(), 0, pt );
1156 break;
1157 }
1158
1159 case EMR_POLYDRAW16:
1160 {
1161 const EMRPOLYDRAW16 *pPolyDraw16 = (const EMRPOLYDRAW16 *)mr;
1162 const POINTS *ptl = pPolyDraw16->apts;
1163 POINT *pts = HeapAlloc(GetProcessHeap(), 0, pPolyDraw16->cpts * sizeof(POINT));
1164 DWORD i;
1165
1166 /* NB abTypes array doesn't start at pPolyDraw16->abTypes. It's actually
1167 pPolyDraw16->apts + pPolyDraw16->cpts. */
1168 const BYTE *types = (BYTE*)(pPolyDraw16->apts + pPolyDraw16->cpts);
1169
1170 if (!pts)
1171 break;
1172
1173 for (i = 0; i < pPolyDraw16->cpts; ++i)
1174 {
1175 pts[i].x = ptl[i].x;
1176 pts[i].y = ptl[i].y;
1177 }
1178
1179 PolyDraw(hdc, pts, types, pPolyDraw16->cpts);
1180 HeapFree(GetProcessHeap(), 0, pts);
1181 break;
1182 }
1183
1184 case EMR_STRETCHDIBITS:
1185 {
1186 const EMRSTRETCHDIBITS *pStretchDIBits = (const EMRSTRETCHDIBITS *)mr;
1187
1189 pStretchDIBits->xDest,
1190 pStretchDIBits->yDest,
1191 pStretchDIBits->cxDest,
1192 pStretchDIBits->cyDest,
1193 pStretchDIBits->xSrc,
1194 pStretchDIBits->ySrc,
1195 pStretchDIBits->cxSrc,
1196 pStretchDIBits->cySrc,
1197 (const BYTE *)mr + pStretchDIBits->offBitsSrc,
1198 (const BITMAPINFO *)((const BYTE *)mr + pStretchDIBits->offBmiSrc),
1199 pStretchDIBits->iUsageSrc,
1200 pStretchDIBits->dwRop);
1201 break;
1202 }
1203
1204 case EMR_EXTTEXTOUTA:
1205 {
1206 const EMREXTTEXTOUTA *pExtTextOutA = (const EMREXTTEXTOUTA *)mr;
1207 RECT rc;
1208 const INT *dx = NULL;
1209 int old_mode;
1210
1211 rc.left = pExtTextOutA->emrtext.rcl.left;
1212 rc.top = pExtTextOutA->emrtext.rcl.top;
1213 rc.right = pExtTextOutA->emrtext.rcl.right;
1214 rc.bottom = pExtTextOutA->emrtext.rcl.bottom;
1215 TRACE("EMR_EXTTEXTOUTA: x,y = %d, %d. rect = %s. flags %08x\n",
1216 pExtTextOutA->emrtext.ptlReference.x, pExtTextOutA->emrtext.ptlReference.y,
1217 wine_dbgstr_rect(&rc), pExtTextOutA->emrtext.fOptions);
1218
1219 old_mode = SetGraphicsMode(hdc, pExtTextOutA->iGraphicsMode);
1220 /* Reselect the font back into the dc so that the transformation
1221 gets updated. */
1223
1224 /* Linux version of pstoedit produces EMFs with offDx set to 0.
1225 * These files can be enumerated and played under Win98 just
1226 * fine, but at least Win2k chokes on them.
1227 */
1228 if (pExtTextOutA->emrtext.offDx)
1229 dx = (const INT *)((const BYTE *)mr + pExtTextOutA->emrtext.offDx);
1230
1231 ExtTextOutA(hdc, pExtTextOutA->emrtext.ptlReference.x, pExtTextOutA->emrtext.ptlReference.y,
1232 pExtTextOutA->emrtext.fOptions, &rc,
1233 (LPCSTR)((const BYTE *)mr + pExtTextOutA->emrtext.offString), pExtTextOutA->emrtext.nChars,
1234 dx);
1235
1236 SetGraphicsMode(hdc, old_mode);
1237 break;
1238 }
1239
1240 case EMR_EXTTEXTOUTW:
1241 {
1242 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)mr;
1243 RECT rc;
1244 const INT *dx = NULL;
1245 int old_mode;
1246
1247 rc.left = pExtTextOutW->emrtext.rcl.left;
1248 rc.top = pExtTextOutW->emrtext.rcl.top;
1249 rc.right = pExtTextOutW->emrtext.rcl.right;
1250 rc.bottom = pExtTextOutW->emrtext.rcl.bottom;
1251 TRACE("EMR_EXTTEXTOUTW: x,y = %d, %d. rect = %s. flags %08x\n",
1252 pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y,
1253 wine_dbgstr_rect(&rc), pExtTextOutW->emrtext.fOptions);
1254
1255 old_mode = SetGraphicsMode(hdc, pExtTextOutW->iGraphicsMode);
1256 /* Reselect the font back into the dc so that the transformation
1257 gets updated. */
1259
1260 /* Linux version of pstoedit produces EMFs with offDx set to 0.
1261 * These files can be enumerated and played under Win98 just
1262 * fine, but at least Win2k chokes on them.
1263 */
1264 if (pExtTextOutW->emrtext.offDx)
1265 dx = (const INT *)((const BYTE *)mr + pExtTextOutW->emrtext.offDx);
1266
1267 ExtTextOutW(hdc, pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y,
1268 pExtTextOutW->emrtext.fOptions, &rc,
1269 (LPCWSTR)((const BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars,
1270 dx);
1271
1272 SetGraphicsMode(hdc, old_mode);
1273 break;
1274 }
1275
1276 case EMR_CREATEPALETTE:
1277 {
1278 const EMRCREATEPALETTE *lpCreatePal = (const EMRCREATEPALETTE *)mr;
1279
1280 (handletable->objectHandle)[ lpCreatePal->ihPal ] =
1281 CreatePalette( &lpCreatePal->lgpl );
1282
1283 break;
1284 }
1285
1286 case EMR_SELECTPALETTE:
1287 {
1288 const EMRSELECTPALETTE *lpSelectPal = (const EMRSELECTPALETTE *)mr;
1289
1290 if( lpSelectPal->ihPal & 0x80000000 ) {
1291 SelectPalette( hdc, GetStockObject(lpSelectPal->ihPal & 0x7fffffff), TRUE);
1292 } else {
1293 SelectPalette( hdc, (handletable->objectHandle)[lpSelectPal->ihPal], TRUE);
1294 }
1295 break;
1296 }
1297
1298 case EMR_REALIZEPALETTE:
1299 {
1301 break;
1302 }
1303
1305 {
1306 const EMREXTSELECTCLIPRGN *lpRgn = (const EMREXTSELECTCLIPRGN *)mr;
1307#ifdef __REACTOS__
1308 const RGNDATA *pRgnData = (const RGNDATA *)lpRgn->RgnData;
1309 DWORD dwSize = sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT);
1310#endif
1311 HRGN hRgn = 0;
1312
1313 if (mr->nSize >= sizeof(*lpRgn) + sizeof(RGNDATAHEADER))
1314#ifdef __REACTOS__
1315 hRgn = ExtCreateRegion( &info->init_transform, dwSize, pRgnData );
1316#else
1317 hRgn = ExtCreateRegion( &info->init_transform, 0, (const RGNDATA *)lpRgn->RgnData );
1318#endif
1319 ExtSelectClipRgn(hdc, hRgn, (INT)(lpRgn->iMode));
1320 /* ExtSelectClipRgn created a copy of the region */
1322 break;
1323 }
1324
1325 case EMR_SETMETARGN:
1326 {
1327 SetMetaRgn( hdc );
1328 break;
1329 }
1330
1332 {
1333 const EMRSETWORLDTRANSFORM *lpXfrm = (const EMRSETWORLDTRANSFORM *)mr;
1334 info->state.world_transform = lpXfrm->xform;
1335
1336 if (!IS_WIN9X())
1338
1339 break;
1340 }
1341
1342 case EMR_POLYBEZIER:
1343 {
1344 const EMRPOLYBEZIER *lpPolyBez = (const EMRPOLYBEZIER *)mr;
1345 PolyBezier(hdc, (const POINT*)lpPolyBez->aptl, (UINT)lpPolyBez->cptl);
1346 break;
1347 }
1348
1349 case EMR_POLYGON:
1350 {
1351 const EMRPOLYGON *lpPoly = (const EMRPOLYGON *)mr;
1352 Polygon( hdc, (const POINT*)lpPoly->aptl, (UINT)lpPoly->cptl );
1353 break;
1354 }
1355
1356 case EMR_POLYLINE:
1357 {
1358 const EMRPOLYLINE *lpPolyLine = (const EMRPOLYLINE *)mr;
1359 Polyline(hdc, (const POINT*)lpPolyLine->aptl, (UINT)lpPolyLine->cptl);
1360 break;
1361 }
1362
1363 case EMR_POLYBEZIERTO:
1364 {
1365 const EMRPOLYBEZIERTO *lpPolyBezierTo = (const EMRPOLYBEZIERTO *)mr;
1366 PolyBezierTo( hdc, (const POINT*)lpPolyBezierTo->aptl,
1367 (UINT)lpPolyBezierTo->cptl );
1368 break;
1369 }
1370
1371 case EMR_POLYLINETO:
1372 {
1373 const EMRPOLYLINETO *lpPolyLineTo = (const EMRPOLYLINETO *)mr;
1374 PolylineTo( hdc, (const POINT*)lpPolyLineTo->aptl,
1375 (UINT)lpPolyLineTo->cptl );
1376 break;
1377 }
1378
1379 case EMR_POLYPOLYLINE:
1380 {
1381 const EMRPOLYPOLYLINE *pPolyPolyline = (const EMRPOLYPOLYLINE *)mr;
1382 /* NB Points at pPolyPolyline->aPolyCounts + pPolyPolyline->nPolys */
1383
1384 PolyPolyline(hdc, (const POINT*)(pPolyPolyline->aPolyCounts +
1385 pPolyPolyline->nPolys),
1386 pPolyPolyline->aPolyCounts,
1387 pPolyPolyline->nPolys );
1388
1389 break;
1390 }
1391
1392 case EMR_POLYPOLYGON:
1393 {
1394 const EMRPOLYPOLYGON *pPolyPolygon = (const EMRPOLYPOLYGON *)mr;
1395
1396 /* NB Points at pPolyPolygon->aPolyCounts + pPolyPolygon->nPolys */
1397
1398 PolyPolygon(hdc, (const POINT*)(pPolyPolygon->aPolyCounts +
1399 pPolyPolygon->nPolys),
1400 (const INT*)pPolyPolygon->aPolyCounts, pPolyPolygon->nPolys );
1401 break;
1402 }
1403
1404 case EMR_SETBRUSHORGEX:
1405 {
1406 const EMRSETBRUSHORGEX *lpSetBrushOrgEx = (const EMRSETBRUSHORGEX *)mr;
1407
1409 (INT)lpSetBrushOrgEx->ptlOrigin.x,
1410 (INT)lpSetBrushOrgEx->ptlOrigin.y,
1411 NULL );
1412
1413 break;
1414 }
1415
1416 case EMR_SETPIXELV:
1417 {
1418 const EMRSETPIXELV *lpSetPixelV = (const EMRSETPIXELV *)mr;
1419
1420 SetPixelV( hdc,
1421 (INT)lpSetPixelV->ptlPixel.x,
1422 (INT)lpSetPixelV->ptlPixel.y,
1423 lpSetPixelV->crColor );
1424
1425 break;
1426 }
1427
1428 case EMR_SETMAPPERFLAGS:
1429 {
1430 const EMRSETMAPPERFLAGS *lpSetMapperFlags = (const EMRSETMAPPERFLAGS *)mr;
1431
1432 SetMapperFlags( hdc, lpSetMapperFlags->dwFlags );
1433
1434 break;
1435 }
1436
1438 {
1439 const EMRSETCOLORADJUSTMENT *lpSetColorAdjust = (const EMRSETCOLORADJUSTMENT *)mr;
1440
1441 SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment );
1442
1443 break;
1444 }
1445
1446 case EMR_OFFSETCLIPRGN:
1447 {
1448 const EMROFFSETCLIPRGN *lpOffsetClipRgn = (const EMROFFSETCLIPRGN *)mr;
1449
1451 (INT)lpOffsetClipRgn->ptlOffset.x,
1452 (INT)lpOffsetClipRgn->ptlOffset.y );
1453 FIXME("OffsetClipRgn\n");
1454
1455 break;
1456 }
1457
1459 {
1460 const EMREXCLUDECLIPRECT *lpExcludeClipRect = (const EMREXCLUDECLIPRECT *)mr;
1461
1463 lpExcludeClipRect->rclClip.left,
1464 lpExcludeClipRect->rclClip.top,
1465 lpExcludeClipRect->rclClip.right,
1466 lpExcludeClipRect->rclClip.bottom );
1467 FIXME("ExcludeClipRect\n");
1468
1469 break;
1470 }
1471
1473 {
1474 const EMRSCALEVIEWPORTEXTEX *lpScaleViewportExtEx = (const EMRSCALEVIEWPORTEXTEX *)mr;
1475
1476 if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
1477 break;
1478 if (!lpScaleViewportExtEx->xNum || !lpScaleViewportExtEx->xDenom ||
1479 !lpScaleViewportExtEx->yNum || !lpScaleViewportExtEx->yDenom)
1480 break;
1481 info->state.vportExtX = MulDiv(info->state.vportExtX, lpScaleViewportExtEx->xNum,
1482 lpScaleViewportExtEx->xDenom);
1483 info->state.vportExtY = MulDiv(info->state.vportExtY, lpScaleViewportExtEx->yNum,
1484 lpScaleViewportExtEx->yDenom);
1485 if (info->state.vportExtX == 0) info->state.vportExtX = 1;
1486 if (info->state.vportExtY == 0) info->state.vportExtY = 1;
1487 if (info->state.mode == MM_ISOTROPIC)
1489
1490 TRACE("EMRSCALEVIEWPORTEXTEX %d/%d %d/%d\n",
1491 lpScaleViewportExtEx->xNum,lpScaleViewportExtEx->xDenom,
1492 lpScaleViewportExtEx->yNum,lpScaleViewportExtEx->yDenom);
1493
1494 if (!IS_WIN9X())
1496
1497 break;
1498 }
1499
1501 {
1502 const EMRSCALEWINDOWEXTEX *lpScaleWindowExtEx = (const EMRSCALEWINDOWEXTEX *)mr;
1503
1504 if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
1505 break;
1506 if (!lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->xDenom ||
1507 !lpScaleWindowExtEx->yNum || !lpScaleWindowExtEx->yDenom)
1508 break;
1509 info->state.wndExtX = MulDiv(info->state.wndExtX, lpScaleWindowExtEx->xNum,
1510 lpScaleWindowExtEx->xDenom);
1511 info->state.wndExtY = MulDiv(info->state.wndExtY, lpScaleWindowExtEx->yNum,
1512 lpScaleWindowExtEx->yDenom);
1513 if (info->state.wndExtX == 0) info->state.wndExtX = 1;
1514 if (info->state.wndExtY == 0) info->state.wndExtY = 1;
1515 if (info->state.mode == MM_ISOTROPIC)
1517
1518 TRACE("EMRSCALEWINDOWEXTEX %d/%d %d/%d\n",
1519 lpScaleWindowExtEx->xNum,lpScaleWindowExtEx->xDenom,
1520 lpScaleWindowExtEx->yNum,lpScaleWindowExtEx->yDenom);
1521
1522 if (!IS_WIN9X())
1524
1525 break;
1526 }
1527
1529 {
1530 const EMRMODIFYWORLDTRANSFORM *lpModifyWorldTrans = (const EMRMODIFYWORLDTRANSFORM *)mr;
1531
1532 switch(lpModifyWorldTrans->iMode) {
1533 case MWT_IDENTITY:
1534 info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1;
1535 info->state.world_transform.eM12 = info->state.world_transform.eM21 = 0;
1536 info->state.world_transform.eDx = info->state.world_transform.eDy = 0;
1537 if (!IS_WIN9X())
1539 break;
1540 case MWT_LEFTMULTIPLY:
1541 CombineTransform(&info->state.world_transform, &lpModifyWorldTrans->xform,
1542 &info->state.world_transform);
1543 if (!IS_WIN9X())
1544 ModifyWorldTransform(hdc, &lpModifyWorldTrans->xform, MWT_LEFTMULTIPLY);
1545 break;
1546 case MWT_RIGHTMULTIPLY:
1547 CombineTransform(&info->state.world_transform, &info->state.world_transform,
1548 &lpModifyWorldTrans->xform);
1549 if (!IS_WIN9X())
1551 break;
1552 default:
1553 FIXME("Unknown imode %d\n", lpModifyWorldTrans->iMode);
1554 break;
1555 }
1556 break;
1557 }
1558
1559 case EMR_ANGLEARC:
1560 {
1561 const EMRANGLEARC *lpAngleArc = (const EMRANGLEARC *)mr;
1562
1563 AngleArc( hdc,
1564 (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y,
1565 lpAngleArc->nRadius, lpAngleArc->eStartAngle,
1566 lpAngleArc->eSweepAngle );
1567
1568 break;
1569 }
1570
1571 case EMR_ROUNDRECT:
1572 {
1573 const EMRROUNDRECT *lpRoundRect = (const EMRROUNDRECT *)mr;
1574
1575 RoundRect( hdc,
1576 lpRoundRect->rclBox.left,
1577 lpRoundRect->rclBox.top,
1578 lpRoundRect->rclBox.right,
1579 lpRoundRect->rclBox.bottom,
1580 lpRoundRect->szlCorner.cx,
1581 lpRoundRect->szlCorner.cy );
1582
1583 break;
1584 }
1585
1586 case EMR_ARC:
1587 {
1588 const EMRARC *lpArc = (const EMRARC *)mr;
1589
1590 Arc( hdc,
1591 (INT)lpArc->rclBox.left,
1592 (INT)lpArc->rclBox.top,
1593 (INT)lpArc->rclBox.right,
1594 (INT)lpArc->rclBox.bottom,
1595 (INT)lpArc->ptlStart.x,
1596 (INT)lpArc->ptlStart.y,
1597 (INT)lpArc->ptlEnd.x,
1598 (INT)lpArc->ptlEnd.y );
1599
1600 break;
1601 }
1602
1603 case EMR_CHORD:
1604 {
1605 const EMRCHORD *lpChord = (const EMRCHORD *)mr;
1606
1607 Chord( hdc,
1608 (INT)lpChord->rclBox.left,
1609 (INT)lpChord->rclBox.top,
1610 (INT)lpChord->rclBox.right,
1611 (INT)lpChord->rclBox.bottom,
1612 (INT)lpChord->ptlStart.x,
1613 (INT)lpChord->ptlStart.y,
1614 (INT)lpChord->ptlEnd.x,
1615 (INT)lpChord->ptlEnd.y );
1616
1617 break;
1618 }
1619
1620 case EMR_PIE:
1621 {
1622 const EMRPIE *lpPie = (const EMRPIE *)mr;
1623
1624 Pie( hdc,
1625 (INT)lpPie->rclBox.left,
1626 (INT)lpPie->rclBox.top,
1627 (INT)lpPie->rclBox.right,
1628 (INT)lpPie->rclBox.bottom,
1629 (INT)lpPie->ptlStart.x,
1630 (INT)lpPie->ptlStart.y,
1631 (INT)lpPie->ptlEnd.x,
1632 (INT)lpPie->ptlEnd.y );
1633
1634 break;
1635 }
1636
1637 case EMR_ARCTO:
1638 {
1639 const EMRARC *lpArcTo = (const EMRARC *)mr;
1640
1641 ArcTo( hdc,
1642 (INT)lpArcTo->rclBox.left,
1643 (INT)lpArcTo->rclBox.top,
1644 (INT)lpArcTo->rclBox.right,
1645 (INT)lpArcTo->rclBox.bottom,
1646 (INT)lpArcTo->ptlStart.x,
1647 (INT)lpArcTo->ptlStart.y,
1648 (INT)lpArcTo->ptlEnd.x,
1649 (INT)lpArcTo->ptlEnd.y );
1650
1651 break;
1652 }
1653
1654 case EMR_EXTFLOODFILL:
1655 {
1656 const EMREXTFLOODFILL *lpExtFloodFill = (const EMREXTFLOODFILL *)mr;
1657
1659 (INT)lpExtFloodFill->ptlStart.x,
1660 (INT)lpExtFloodFill->ptlStart.y,
1661 lpExtFloodFill->crColor,
1662 (UINT)lpExtFloodFill->iMode );
1663
1664 break;
1665 }
1666
1667 case EMR_POLYDRAW:
1668 {
1669 const EMRPOLYDRAW *lpPolyDraw = (const EMRPOLYDRAW *)mr;
1670 PolyDraw( hdc,
1671 (const POINT*)lpPolyDraw->aptl,
1672 lpPolyDraw->abTypes,
1673 (INT)lpPolyDraw->cptl );
1674
1675 break;
1676 }
1677
1679 {
1680 const EMRSETARCDIRECTION *lpSetArcDirection = (const EMRSETARCDIRECTION *)mr;
1681 SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection );
1682 break;
1683 }
1684
1685 case EMR_SETMITERLIMIT:
1686 {
1687 const EMRSETMITERLIMIT *lpSetMiterLimit = (const EMRSETMITERLIMIT *)mr;
1688 SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL );
1689 break;
1690 }
1691
1692 case EMR_BEGINPATH:
1693 {
1694 BeginPath( hdc );
1695 break;
1696 }
1697
1698 case EMR_ENDPATH:
1699 {
1700 EndPath( hdc );
1701 break;
1702 }
1703
1704 case EMR_CLOSEFIGURE:
1705 {
1706 CloseFigure( hdc );
1707 break;
1708 }
1709
1710 case EMR_FILLPATH:
1711 {
1712 /*const EMRFILLPATH lpFillPath = (const EMRFILLPATH *)mr;*/
1713 FillPath( hdc );
1714 break;
1715 }
1716
1718 {
1719 /*const EMRSTROKEANDFILLPATH lpStrokeAndFillPath = (const EMRSTROKEANDFILLPATH *)mr;*/
1721 break;
1722 }
1723
1724 case EMR_STROKEPATH:
1725 {
1726 /*const EMRSTROKEPATH lpStrokePath = (const EMRSTROKEPATH *)mr;*/
1727 StrokePath( hdc );
1728 break;
1729 }
1730
1731 case EMR_FLATTENPATH:
1732 {
1733 FlattenPath( hdc );
1734 break;
1735 }
1736
1737 case EMR_WIDENPATH:
1738 {
1739 WidenPath( hdc );
1740 break;
1741 }
1742
1743 case EMR_SELECTCLIPPATH:
1744 {
1745 const EMRSELECTCLIPPATH *lpSelectClipPath = (const EMRSELECTCLIPPATH *)mr;
1746 SelectClipPath( hdc, (INT)lpSelectClipPath->iMode );
1747 break;
1748 }
1749
1750 case EMR_ABORTPATH:
1751 {
1752 AbortPath( hdc );
1753 break;
1754 }
1755
1757 {
1758 PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr;
1759 (handletable->objectHandle)[lpCreateColorSpace->ihCS] =
1760 CreateColorSpaceA( &lpCreateColorSpace->lcs );
1761 break;
1762 }
1763
1764 case EMR_SETCOLORSPACE:
1765 {
1766 const EMRSETCOLORSPACE *lpSetColorSpace = (const EMRSETCOLORSPACE *)mr;
1768 (handletable->objectHandle)[lpSetColorSpace->ihCS] );
1769 break;
1770 }
1771
1773 {
1774 const EMRDELETECOLORSPACE *lpDeleteColorSpace = (const EMRDELETECOLORSPACE *)mr;
1775 DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] );
1776 break;
1777 }
1778
1779 case EMR_SETICMMODE:
1780 {
1781 const EMRSETICMMODE *lpSetICMMode = (const EMRSETICMMODE *)mr;
1782 SetICMMode( hdc, (INT)lpSetICMMode->iMode );
1783 break;
1784 }
1785
1786 case EMR_PIXELFORMAT:
1787 {
1789 const EMRPIXELFORMAT *lpPixelFormat = (const EMRPIXELFORMAT *)mr;
1790
1791 iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd );
1792 SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd );
1793
1794 break;
1795 }
1796
1798 {
1799 const EMRSETPALETTEENTRIES *lpSetPaletteEntries = (const EMRSETPALETTEENTRIES *)mr;
1800
1801 SetPaletteEntries( (handletable->objectHandle)[lpSetPaletteEntries->ihPal],
1802 (UINT)lpSetPaletteEntries->iStart,
1803 (UINT)lpSetPaletteEntries->cEntries,
1804 lpSetPaletteEntries->aPalEntries );
1805
1806 break;
1807 }
1808
1809 case EMR_RESIZEPALETTE:
1810 {
1811 const EMRRESIZEPALETTE *lpResizePalette = (const EMRRESIZEPALETTE *)mr;
1812
1813 ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal],
1814 (UINT)lpResizePalette->cEntries );
1815
1816 break;
1817 }
1818
1820 {
1821 const EMRCREATEDIBPATTERNBRUSHPT *lpCreate = (const EMRCREATEDIBPATTERNBRUSHPT *)mr;
1822 LPVOID lpPackedStruct;
1823
1824 /* Check that offsets and data are contained within the record
1825 * (including checking for wrap-arounds).
1826 */
1827 if ( lpCreate->offBmi + lpCreate->cbBmi > mr->nSize
1828 || lpCreate->offBits + lpCreate->cbBits > mr->nSize
1829 || lpCreate->offBmi + lpCreate->cbBmi < lpCreate->offBmi
1830 || lpCreate->offBits + lpCreate->cbBits < lpCreate->offBits )
1831 {
1832 ERR("Invalid EMR_CREATEDIBPATTERNBRUSHPT record\n");
1833 break;
1834 }
1835
1836 /* This is a BITMAPINFO struct followed directly by bitmap bits */
1837 lpPackedStruct = HeapAlloc( GetProcessHeap(), 0,
1838 lpCreate->cbBmi + lpCreate->cbBits );
1839 if(!lpPackedStruct)
1840 {
1842 break;
1843 }
1844
1845 /* Now pack this structure */
1846 memcpy( lpPackedStruct,
1847 ((const BYTE *)lpCreate) + lpCreate->offBmi,
1848 lpCreate->cbBmi );
1849 memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi,
1850 ((const BYTE *)lpCreate) + lpCreate->offBits,
1851 lpCreate->cbBits );
1852
1853 (handletable->objectHandle)[lpCreate->ihBrush] =
1854 CreateDIBPatternBrushPt( lpPackedStruct,
1855 (UINT)lpCreate->iUsage );
1856
1857 HeapFree(GetProcessHeap(), 0, lpPackedStruct);
1858 break;
1859 }
1860
1862 {
1863 const EMRCREATEMONOBRUSH *pCreateMonoBrush = (const EMRCREATEMONOBRUSH *)mr;
1864 const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pCreateMonoBrush->offBmi);
1865 HBITMAP hBmp;
1866
1867 /* Need to check if the bitmap is monochrome, and if the
1868 two colors are really black and white */
1869 if (pCreateMonoBrush->iUsage == DIB_PAL_MONO)
1870 {
1871 BITMAP bm;
1872
1873 /* Undocumented iUsage indicates a mono bitmap with no palette table,
1874 * aligned to 32 rather than 16 bits.
1875 */
1876 bm.bmType = 0;
1877 bm.bmWidth = pbi->bmiHeader.biWidth;
1878 bm.bmHeight = abs(pbi->bmiHeader.biHeight);
1879 bm.bmWidthBytes = 4 * ((pbi->bmiHeader.biWidth + 31) / 32);
1880 bm.bmPlanes = pbi->bmiHeader.biPlanes;
1881 bm.bmBitsPixel = pbi->bmiHeader.biBitCount;
1882 bm.bmBits = (BYTE *)mr + pCreateMonoBrush->offBits;
1883 hBmp = CreateBitmapIndirect(&bm);
1884 }
1885 else if (is_dib_monochrome(pbi))
1886 {
1887 /* Top-down DIBs have a negative height */
1888 LONG height = pbi->bmiHeader.biHeight;
1889
1890 hBmp = CreateBitmap(pbi->bmiHeader.biWidth, abs(height), 1, 1, NULL);
1891 SetDIBits(hdc, hBmp, 0, pbi->bmiHeader.biHeight,
1892 (const BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
1893 }
1894 else
1895 {
1897 (const BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
1898 }
1899
1900 (handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp);
1901
1902 /* CreatePatternBrush created a copy of the bitmap */
1903 DeleteObject(hBmp);
1904 break;
1905 }
1906
1907 case EMR_BITBLT:
1908 {
1909 const EMRBITBLT *pBitBlt = (const EMRBITBLT *)mr;
1910
1911 if(pBitBlt->offBmiSrc == 0) { /* Record is a PatBlt */
1912 PatBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest,
1913 pBitBlt->dwRop);
1914 } else { /* BitBlt */
1916 HBRUSH hBrush, hBrushOld;
1917 HBITMAP hBmp = 0, hBmpOld = 0;
1918 const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pBitBlt->offBmiSrc);
1919
1921 SetWorldTransform(hdcSrc, &pBitBlt->xformSrc);
1922
1923 hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc);
1924 hBrushOld = SelectObject(hdcSrc, hBrush);
1925 PatBlt(hdcSrc, pBitBlt->rclBounds.left, pBitBlt->rclBounds.top,
1926 pBitBlt->rclBounds.right - pBitBlt->rclBounds.left,
1927 pBitBlt->rclBounds.bottom - pBitBlt->rclBounds.top, PATCOPY);
1928 SelectObject(hdcSrc, hBrushOld);
1929 DeleteObject(hBrush);
1930
1932 (const BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
1933 hBmpOld = SelectObject(hdcSrc, hBmp);
1934
1935 BitBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest,
1936 hdcSrc, pBitBlt->xSrc, pBitBlt->ySrc, pBitBlt->dwRop);
1937
1938 SelectObject(hdcSrc, hBmpOld);
1939 DeleteObject(hBmp);
1941 }
1942 break;
1943 }
1944
1945 case EMR_STRETCHBLT:
1946 {
1947 const EMRSTRETCHBLT *pStretchBlt = (const EMRSTRETCHBLT *)mr;
1948
1949 TRACE("EMR_STRETCHBLT: %d, %d %dx%d -> %d, %d %dx%d. rop %08x offBitsSrc %d\n",
1950 pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc,
1951 pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
1952 pStretchBlt->dwRop, pStretchBlt->offBitsSrc);
1953
1954 if(pStretchBlt->offBmiSrc == 0) { /* Record is a PatBlt */
1955 PatBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
1956 pStretchBlt->dwRop);
1957 } else { /* StretchBlt */
1959 HBRUSH hBrush, hBrushOld;
1960 HBITMAP hBmp = 0, hBmpOld = 0;
1961 const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pStretchBlt->offBmiSrc);
1962
1964 SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc);
1965
1966 hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc);
1967 hBrushOld = SelectObject(hdcSrc, hBrush);
1968 PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top,
1969 pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left,
1970 pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY);
1971 SelectObject(hdcSrc, hBrushOld);
1972 DeleteObject(hBrush);
1973
1975 (const BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
1976 hBmpOld = SelectObject(hdcSrc, hBmp);
1977
1978 StretchBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
1979 hdcSrc, pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc,
1980 pStretchBlt->dwRop);
1981
1982 SelectObject(hdcSrc, hBmpOld);
1983 DeleteObject(hBmp);
1985 }
1986 break;
1987 }
1988
1989 case EMR_ALPHABLEND:
1990 {
1991 const EMRALPHABLEND *pAlphaBlend = (const EMRALPHABLEND *)mr;
1992
1993 TRACE("EMR_ALPHABLEND: %d, %d %dx%d -> %d, %d %dx%d. blendfn %08x offBitsSrc %d\n",
1994 pAlphaBlend->xSrc, pAlphaBlend->ySrc, pAlphaBlend->cxSrc, pAlphaBlend->cySrc,
1995 pAlphaBlend->xDest, pAlphaBlend->yDest, pAlphaBlend->cxDest, pAlphaBlend->cyDest,
1996 pAlphaBlend->dwRop, pAlphaBlend->offBitsSrc);
1997
1998 if(pAlphaBlend->offBmiSrc == 0) {
1999 FIXME("EMR_ALPHABLEND: offBmiSrc == 0\n");
2000 } else {
2002 HBITMAP hBmp = 0, hBmpOld = 0;
2003 const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pAlphaBlend->offBmiSrc);
2004 void *bits;
2005
2007 SetWorldTransform(hdcSrc, &pAlphaBlend->xformSrc);
2008
2009 hBmp = CreateDIBSection(hdc, pbi, pAlphaBlend->iUsageSrc, &bits, NULL, 0);
2010 memcpy(bits, (const BYTE *)mr + pAlphaBlend->offBitsSrc, pAlphaBlend->cbBitsSrc);
2011 hBmpOld = SelectObject(hdcSrc, hBmp);
2012
2013 GdiAlphaBlend(hdc, pAlphaBlend->xDest, pAlphaBlend->yDest, pAlphaBlend->cxDest, pAlphaBlend->cyDest,
2014 hdcSrc, pAlphaBlend->xSrc, pAlphaBlend->ySrc, pAlphaBlend->cxSrc, pAlphaBlend->cySrc,
2015 *(BLENDFUNCTION *)&pAlphaBlend->dwRop);
2016
2017 SelectObject(hdcSrc, hBmpOld);
2018 DeleteObject(hBmp);
2020 }
2021 break;
2022 }
2023
2024 case EMR_MASKBLT:
2025 {
2026 const EMRMASKBLT *pMaskBlt = (const EMRMASKBLT *)mr;
2028 HBRUSH hBrush, hBrushOld;
2029 HBITMAP hBmp, hBmpOld, hBmpMask;
2030 const BITMAPINFO *pbi;
2031
2033 SetWorldTransform(hdcSrc, &pMaskBlt->xformSrc);
2034
2035 hBrush = CreateSolidBrush(pMaskBlt->crBkColorSrc);
2036 hBrushOld = SelectObject(hdcSrc, hBrush);
2037 PatBlt(hdcSrc, pMaskBlt->rclBounds.left, pMaskBlt->rclBounds.top,
2038 pMaskBlt->rclBounds.right - pMaskBlt->rclBounds.left,
2039 pMaskBlt->rclBounds.bottom - pMaskBlt->rclBounds.top, PATCOPY);
2040 SelectObject(hdcSrc, hBrushOld);
2041 DeleteObject(hBrush);
2042
2043 pbi = (const BITMAPINFO *)((const BYTE *)mr + pMaskBlt->offBmiMask);
2044 hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight,
2045 1, 1, NULL);
2046 SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight,
2047 (const BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
2048
2049 pbi = (const BITMAPINFO *)((const BYTE *)mr + pMaskBlt->offBmiSrc);
2051 (const BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc);
2052 hBmpOld = SelectObject(hdcSrc, hBmp);
2053 MaskBlt(hdc,
2054 pMaskBlt->xDest,
2055 pMaskBlt->yDest,
2056 pMaskBlt->cxDest,
2057 pMaskBlt->cyDest,
2058 hdcSrc,
2059 pMaskBlt->xSrc,
2060 pMaskBlt->ySrc,
2061 hBmpMask,
2062 pMaskBlt->xMask,
2063 pMaskBlt->yMask,
2064 pMaskBlt->dwRop);
2065 SelectObject(hdcSrc, hBmpOld);
2066 DeleteObject(hBmp);
2067 DeleteObject(hBmpMask);
2069 break;
2070 }
2071
2072 case EMR_PLGBLT:
2073 {
2074 const EMRPLGBLT *pPlgBlt = (const EMRPLGBLT *)mr;
2076 HBRUSH hBrush, hBrushOld;
2077 HBITMAP hBmp, hBmpOld, hBmpMask;
2078 const BITMAPINFO *pbi;
2079 POINT pts[3];
2080
2082 SetWorldTransform(hdcSrc, &pPlgBlt->xformSrc);
2083
2084 pts[0].x = pPlgBlt->aptlDest[0].x; pts[0].y = pPlgBlt->aptlDest[0].y;
2085 pts[1].x = pPlgBlt->aptlDest[1].x; pts[1].y = pPlgBlt->aptlDest[1].y;
2086 pts[2].x = pPlgBlt->aptlDest[2].x; pts[2].y = pPlgBlt->aptlDest[2].y;
2087
2088 hBrush = CreateSolidBrush(pPlgBlt->crBkColorSrc);
2089 hBrushOld = SelectObject(hdcSrc, hBrush);
2090 PatBlt(hdcSrc, pPlgBlt->rclBounds.left, pPlgBlt->rclBounds.top,
2091 pPlgBlt->rclBounds.right - pPlgBlt->rclBounds.left,
2092 pPlgBlt->rclBounds.bottom - pPlgBlt->rclBounds.top, PATCOPY);
2093 SelectObject(hdcSrc, hBrushOld);
2094 DeleteObject(hBrush);
2095
2096 pbi = (const BITMAPINFO *)((const BYTE *)mr + pPlgBlt->offBmiMask);
2097 hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight,
2098 1, 1, NULL);
2099 SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight,
2100 (const BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
2101
2102 pbi = (const BITMAPINFO *)((const BYTE *)mr + pPlgBlt->offBmiSrc);
2104 (const BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc);
2105 hBmpOld = SelectObject(hdcSrc, hBmp);
2106 PlgBlt(hdc,
2107 pts,
2108 hdcSrc,
2109 pPlgBlt->xSrc,
2110 pPlgBlt->ySrc,
2111 pPlgBlt->cxSrc,
2112 pPlgBlt->cySrc,
2113 hBmpMask,
2114 pPlgBlt->xMask,
2115 pPlgBlt->yMask);
2116 SelectObject(hdcSrc, hBmpOld);
2117 DeleteObject(hBmp);
2118 DeleteObject(hBmpMask);
2120 break;
2121 }
2122
2124 {
2125 const EMRSETDIBITSTODEVICE *pSetDIBitsToDevice = (const EMRSETDIBITSTODEVICE *)mr;
2126
2128 pSetDIBitsToDevice->xDest,
2129 pSetDIBitsToDevice->yDest,
2130 pSetDIBitsToDevice->cxSrc,
2131 pSetDIBitsToDevice->cySrc,
2132 pSetDIBitsToDevice->xSrc,
2133 pSetDIBitsToDevice->ySrc,
2134 pSetDIBitsToDevice->iStartScan,
2135 pSetDIBitsToDevice->cScans,
2136 (const BYTE *)mr + pSetDIBitsToDevice->offBitsSrc,
2137 (const BITMAPINFO *)((const BYTE *)mr + pSetDIBitsToDevice->offBmiSrc),
2138 pSetDIBitsToDevice->iUsageSrc);
2139 break;
2140 }
2141
2142 case EMR_POLYTEXTOUTA:
2143 {
2144 const EMRPOLYTEXTOUTA *pPolyTextOutA = (const EMRPOLYTEXTOUTA *)mr;
2145 POLYTEXTA *polytextA = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutA->cStrings * sizeof(POLYTEXTA));
2146 LONG i;
2147 XFORM xform, xformOld;
2148 int gModeOld;
2149
2150 gModeOld = SetGraphicsMode(hdc, pPolyTextOutA->iGraphicsMode);
2151 GetWorldTransform(hdc, &xformOld);
2152
2153 xform.eM11 = pPolyTextOutA->exScale;
2154 xform.eM12 = 0.0;
2155 xform.eM21 = 0.0;
2156 xform.eM22 = pPolyTextOutA->eyScale;
2157 xform.eDx = 0.0;
2158 xform.eDy = 0.0;
2159 SetWorldTransform(hdc, &xform);
2160
2161 /* Set up POLYTEXTA structures */
2162 for(i = 0; i < pPolyTextOutA->cStrings; i++)
2163 {
2164 polytextA[i].x = pPolyTextOutA->aemrtext[i].ptlReference.x;
2165 polytextA[i].y = pPolyTextOutA->aemrtext[i].ptlReference.y;
2166 polytextA[i].n = pPolyTextOutA->aemrtext[i].nChars;
2167 polytextA[i].lpstr = (LPCSTR)((const BYTE *)mr + pPolyTextOutA->aemrtext[i].offString);
2168 polytextA[i].uiFlags = pPolyTextOutA->aemrtext[i].fOptions;
2169 polytextA[i].rcl.left = pPolyTextOutA->aemrtext[i].rcl.left;
2170 polytextA[i].rcl.right = pPolyTextOutA->aemrtext[i].rcl.right;
2171 polytextA[i].rcl.top = pPolyTextOutA->aemrtext[i].rcl.top;
2172 polytextA[i].rcl.bottom = pPolyTextOutA->aemrtext[i].rcl.bottom;
2173 polytextA[i].pdx = (int *)((BYTE *)mr + pPolyTextOutA->aemrtext[i].offDx);
2174 }
2175 PolyTextOutA(hdc, polytextA, pPolyTextOutA->cStrings);
2176 HeapFree(GetProcessHeap(), 0, polytextA);
2177
2178 SetWorldTransform(hdc, &xformOld);
2179 SetGraphicsMode(hdc, gModeOld);
2180 break;
2181 }
2182
2183 case EMR_POLYTEXTOUTW:
2184 {
2185 const EMRPOLYTEXTOUTW *pPolyTextOutW = (const EMRPOLYTEXTOUTW *)mr;
2186 POLYTEXTW *polytextW = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutW->cStrings * sizeof(POLYTEXTW));
2187 LONG i;
2188 XFORM xform, xformOld;
2189 int gModeOld;
2190
2191 gModeOld = SetGraphicsMode(hdc, pPolyTextOutW->iGraphicsMode);
2192 GetWorldTransform(hdc, &xformOld);
2193
2194 xform.eM11 = pPolyTextOutW->exScale;
2195 xform.eM12 = 0.0;
2196 xform.eM21 = 0.0;
2197 xform.eM22 = pPolyTextOutW->eyScale;
2198 xform.eDx = 0.0;
2199 xform.eDy = 0.0;
2200 SetWorldTransform(hdc, &xform);
2201
2202 /* Set up POLYTEXTW structures */
2203 for(i = 0; i < pPolyTextOutW->cStrings; i++)
2204 {
2205 polytextW[i].x = pPolyTextOutW->aemrtext[i].ptlReference.x;
2206 polytextW[i].y = pPolyTextOutW->aemrtext[i].ptlReference.y;
2207 polytextW[i].n = pPolyTextOutW->aemrtext[i].nChars;
2208 polytextW[i].lpstr = (LPCWSTR)((const BYTE *)mr + pPolyTextOutW->aemrtext[i].offString);
2209 polytextW[i].uiFlags = pPolyTextOutW->aemrtext[i].fOptions;
2210 polytextW[i].rcl.left = pPolyTextOutW->aemrtext[i].rcl.left;
2211 polytextW[i].rcl.right = pPolyTextOutW->aemrtext[i].rcl.right;
2212 polytextW[i].rcl.top = pPolyTextOutW->aemrtext[i].rcl.top;
2213 polytextW[i].rcl.bottom = pPolyTextOutW->aemrtext[i].rcl.bottom;
2214 polytextW[i].pdx = (int *)((BYTE *)mr + pPolyTextOutW->aemrtext[i].offDx);
2215 }
2216 PolyTextOutW(hdc, polytextW, pPolyTextOutW->cStrings);
2217 HeapFree(GetProcessHeap(), 0, polytextW);
2218
2219 SetWorldTransform(hdc, &xformOld);
2220 SetGraphicsMode(hdc, gModeOld);
2221 break;
2222 }
2223
2224 case EMR_FILLRGN:
2225 {
2226 const EMRFILLRGN *pFillRgn = (const EMRFILLRGN *)mr;
2227 HRGN hRgn = ExtCreateRegion(NULL, pFillRgn->cbRgnData, (const RGNDATA *)pFillRgn->RgnData);
2228 FillRgn(hdc,
2229 hRgn,
2230 (handletable->objectHandle)[pFillRgn->ihBrush]);
2232 break;
2233 }
2234
2235 case EMR_FRAMERGN:
2236 {
2237 const EMRFRAMERGN *pFrameRgn = (const EMRFRAMERGN *)mr;
2238 HRGN hRgn = ExtCreateRegion(NULL, pFrameRgn->cbRgnData, (const RGNDATA *)pFrameRgn->RgnData);
2239 FrameRgn(hdc,
2240 hRgn,
2241 (handletable->objectHandle)[pFrameRgn->ihBrush],
2242 pFrameRgn->szlStroke.cx,
2243 pFrameRgn->szlStroke.cy);
2245 break;
2246 }
2247
2248 case EMR_INVERTRGN:
2249 {
2250 const EMRINVERTRGN *pInvertRgn = (const EMRINVERTRGN *)mr;
2251 HRGN hRgn = ExtCreateRegion(NULL, pInvertRgn->cbRgnData, (const RGNDATA *)pInvertRgn->RgnData);
2252 InvertRgn(hdc, hRgn);
2254 break;
2255 }
2256
2257 case EMR_PAINTRGN:
2258 {
2259 const EMRPAINTRGN *pPaintRgn = (const EMRPAINTRGN *)mr;
2260 HRGN hRgn = ExtCreateRegion(NULL, pPaintRgn->cbRgnData, (const RGNDATA *)pPaintRgn->RgnData);
2261 PaintRgn(hdc, hRgn);
2263 break;
2264 }
2265
2266 case EMR_SETTEXTJUSTIFICATION:
2267 {
2268 const EMRSETTEXTJUSTIFICATION *pSetTextJust = (const EMRSETTEXTJUSTIFICATION *)mr;
2269 SetTextJustification(hdc, pSetTextJust->nBreakExtra, pSetTextJust->nBreakCount);
2270 break;
2271 }
2272
2273 case EMR_SETLAYOUT:
2274 {
2275 const EMRSETLAYOUT *pSetLayout = (const EMRSETLAYOUT *)mr;
2276 SetLayout(hdc, pSetLayout->iMode);
2277 break;
2278 }
2279
2280 case EMR_GRADIENTFILL:
2281 {
2282 EMRGRADIENTFILL *grad = (EMRGRADIENTFILL *)mr;
2283 GdiGradientFill( hdc, grad->Ver, grad->nVer, grad->Ver + grad->nVer,
2284 grad->nTri, grad->ulMode );
2285 break;
2286 }
2287
2288 case EMR_DRAWESCAPE:
2289 {
2290 PEMRESCAPE pemr = (PEMRESCAPE)mr;
2291 DrawEscape( hdc, pemr->iEsc, pemr->cjIn, (LPCSTR)pemr->Data );
2292 break;
2293 }
2294
2295 case EMR_EXTESCAPE:
2296 {
2297 PEMRESCAPE pemr = (PEMRESCAPE)mr;
2298 ExtEscape( hdc, pemr->iEsc, pemr->cjIn, (LPCSTR)pemr->Data, 0, NULL );
2299 break;
2300 }
2301
2302 case EMR_NAMEDESCAPE:
2303 {
2305 INT rounded_size = (pemr->cjIn+3) & ~3;
2306 NamedEscape( hdc, (PWCHAR)&pemr->Data[rounded_size], pemr->iEsc, pemr->cjIn, (LPSTR)pemr->Data, 0, NULL );
2307 break;
2308 }
2309
2310 case EMR_GLSRECORD:
2312 case EMR_STARTDOC:
2313 case EMR_SMALLTEXTOUT:
2314 case EMR_FORCEUFIMAPPING:
2315 case EMR_COLORCORRECTPALETTE:
2316 case EMR_SETICMPROFILEA:
2317 case EMR_SETICMPROFILEW:
2318 case EMR_TRANSPARENTBLT:
2319 case EMR_SETLINKEDUFI:
2320 case EMR_COLORMATCHTOTARGETW:
2321 case EMR_CREATECOLORSPACEW:
2322
2323 default:
2324 /* From docs: If PlayEnhMetaFileRecord doesn't recognize a
2325 record then ignore and return TRUE. */
2326 FIXME("type %d is unimplemented\n", type);
2327 break;
2328 }
2329 tmprc.left = tmprc.top = 0;
2330 tmprc.right = tmprc.bottom = 1000;
2331 LPtoDP(hdc, (POINT*)&tmprc, 2);
2332 TRACE("L:0,0 - 1000,1000 -> D:%s\n", wine_dbgstr_rect(&tmprc));
2333
2334 return TRUE;
2335}
2336
2337/*****************************************************************************
2338 *
2339 * EnumEnhMetaFile (GDI32.@)
2340 *
2341 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
2342 * for each
2343 * record. Returns when either every record has been used or
2344 * when _EnhMetaFunc_ returns FALSE.
2345 *
2346 *
2347 * RETURNS
2348 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
2349 * returns FALSE.
2350 *
2351 * BUGS
2352 * Ignores rect.
2353 *
2354 * NOTES
2355 * This function behaves differently in Win9x and WinNT.
2356 *
2357 * In WinNT, the DC's world transform is updated as the EMF changes
2358 * the Window/Viewport Extent and Origin or its world transform.
2359 * The actual Window/Viewport Extent and Origin are left untouched.
2360 *
2361 * In Win9x, the DC is left untouched, and PlayEnhMetaFileRecord
2362 * updates the scaling itself but only just before a record that
2363 * writes anything to the DC.
2364 *
2365 * I'm not sure where the data (enum_emh_data) is stored in either
2366 * version. For this implementation, it is stored before the handle
2367 * table, but it could be stored in the DC, in the EMF handle or in
2368 * TLS.
2369 * MJM 5 Oct 2002
2370 */
2372 HDC hdc, /* [in] device context to pass to _EnhMetaFunc_ */
2373 HENHMETAFILE hmf, /* [in] EMF to walk */
2374 ENHMFENUMPROC callback, /* [in] callback function */
2375 LPVOID data, /* [in] optional data for callback function */
2376 const RECT *lpRect /* [in] bounding rectangle for rendered metafile */
2377 )
2378{
2379 BOOL ret;
2380 ENHMETAHEADER *emh;
2381 ENHMETARECORD *emr;
2382 DWORD offset;
2383 UINT i;
2384 HANDLETABLE *ht;
2385 INT savedMode = 0;
2386 XFORM savedXform;
2387 HPEN hPen = NULL;
2388 HBRUSH hBrush = NULL;
2389 HFONT hFont = NULL;
2390 HRGN hRgn = NULL;
2392 SIZE vp_size, win_size;
2393 POINT vp_org, win_org;
2394 INT mapMode = MM_TEXT, old_align = 0, old_rop2 = 0, old_arcdir = 0, old_polyfill = 0, old_stretchblt = 0;
2395 COLORREF old_text_color = 0, old_bk_color = 0;
2396
2397 if(!lpRect && hdc)
2398 {
2400 return FALSE;
2401 }
2402
2403 emh = EMF_GetEnhMetaHeader(hmf);
2404 if(!emh) {
2406 return FALSE;
2407 }
2408
2410 sizeof (enum_emh_data) + sizeof(HANDLETABLE) * emh->nHandles );
2411 if(!info)
2412 {
2414 return FALSE;
2415 }
2416 info->state.mode = MM_TEXT;
2417 info->state.wndOrgX = 0;
2418 info->state.wndOrgY = 0;
2419 info->state.wndExtX = 1;
2420 info->state.wndExtY = 1;
2421 info->state.vportOrgX = 0;
2422 info->state.vportOrgY = 0;
2423 info->state.vportExtX = 1;
2424 info->state.vportExtY = 1;
2425 info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1;
2426 info->state.world_transform.eM12 = info->state.world_transform.eM21 = 0;
2427 info->state.world_transform.eDx = info->state.world_transform.eDy = 0;
2428
2429 info->state.next = NULL;
2430 info->save_level = 0;
2431 info->saved_state = NULL;
2432 info->init_transform = info->state.world_transform;
2433
2434 ht = (HANDLETABLE*) &info[1];
2435 ht->objectHandle[0] = hmf;
2436 for(i = 1; i < emh->nHandles; i++)
2437 ht->objectHandle[i] = NULL;
2438
2439 if(hdc && !is_meta_dc( hdc ))
2440 {
2441 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
2442 GetWorldTransform(hdc, &savedXform);
2443 GetViewportExtEx(hdc, &vp_size);
2444 GetWindowExtEx(hdc, &win_size);
2445 GetViewportOrgEx(hdc, &vp_org);
2446 GetWindowOrgEx(hdc, &win_org);
2447 mapMode = GetMapMode(hdc);
2448
2449 /* save DC */
2450 hPen = GetCurrentObject(hdc, OBJ_PEN);
2451 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
2453
2454 hRgn = CreateRectRgn(0, 0, 0, 0);
2455 if (!GetClipRgn(hdc, hRgn))
2456 {
2458 hRgn = 0;
2459 }
2460
2461 old_text_color = SetTextColor(hdc, RGB(0,0,0));
2462 old_bk_color = SetBkColor(hdc, RGB(0xff, 0xff, 0xff));
2463 old_align = SetTextAlign(hdc, 0);
2464 old_rop2 = SetROP2(hdc, R2_COPYPEN);
2466 old_polyfill = SetPolyFillMode(hdc, ALTERNATE);
2467 old_stretchblt = SetStretchBltMode(hdc, BLACKONWHITE);
2468
2469 if (!IS_WIN9X() )
2470 {
2471 /* WinNT combines the vp/win ext/org info into a transform */
2472 double xscale, yscale;
2473 xscale = (double)vp_size.cx / (double)win_size.cx;
2474 yscale = (double)vp_size.cy / (double)win_size.cy;
2475 info->init_transform.eM11 = xscale;
2476 info->init_transform.eM12 = 0.0;
2477 info->init_transform.eM21 = 0.0;
2478 info->init_transform.eM22 = yscale;
2479 info->init_transform.eDx = (double)vp_org.x - xscale * (double)win_org.x;
2480 info->init_transform.eDy = (double)vp_org.y - yscale * (double)win_org.y;
2481
2482 CombineTransform(&info->init_transform, &savedXform, &info->init_transform);
2483 }
2484
2485 if ( lpRect && WIDTH(emh->rclFrame) && HEIGHT(emh->rclFrame) )
2486 {
2487 double xSrcPixSize, ySrcPixSize, xscale, yscale;
2488 XFORM xform;
2489
2490 TRACE("rect: %s. rclFrame: (%d,%d)-(%d,%d)\n", wine_dbgstr_rect(lpRect),
2491 emh->rclFrame.left, emh->rclFrame.top, emh->rclFrame.right,
2492 emh->rclFrame.bottom);
2493
2494 xSrcPixSize = (double) emh->szlMillimeters.cx / emh->szlDevice.cx;
2495 ySrcPixSize = (double) emh->szlMillimeters.cy / emh->szlDevice.cy;
2496 xscale = (double) WIDTH(*lpRect) * 100.0 /
2497 WIDTH(emh->rclFrame) * xSrcPixSize;
2498 yscale = (double) HEIGHT(*lpRect) * 100.0 /
2499 HEIGHT(emh->rclFrame) * ySrcPixSize;
2500 TRACE("xscale = %f, yscale = %f\n", xscale, yscale);
2501
2502 xform.eM11 = xscale;
2503 xform.eM12 = 0;
2504 xform.eM21 = 0;
2505 xform.eM22 = yscale;
2506 xform.eDx = (double) lpRect->left - (double) WIDTH(*lpRect) / WIDTH(emh->rclFrame) * emh->rclFrame.left;
2507 xform.eDy = (double) lpRect->top - (double) HEIGHT(*lpRect) / HEIGHT(emh->rclFrame) * emh->rclFrame.top;
2508
2509 CombineTransform(&info->init_transform, &xform, &info->init_transform);
2510 }
2511
2512 /* WinNT resets the current vp/win org/ext */
2513 if ( !IS_WIN9X() )
2514 {
2516 SetWindowOrgEx(hdc, 0, 0, NULL);
2517 SetViewportOrgEx(hdc, 0, 0, NULL);
2519 }
2520 }
2521
2522 ret = TRUE;
2523 offset = 0;
2524 while(ret && offset < emh->nBytes)
2525 {
2526 emr = (ENHMETARECORD *)((char *)emh + offset);
2527
2528 if (offset + 8 > emh->nBytes ||
2529 offset > offset + emr->nSize ||
2530 offset + emr->nSize > emh->nBytes)
2531 {
2532 WARN("record truncated\n");
2533 break;
2534 }
2535
2536 /* In Win9x mode we update the xform if the record will produce output */
2537 if (hdc && IS_WIN9X() && emr_produces_output(emr->iType))
2539
2540 TRACE("Calling EnumFunc with record %s, size %d\n", get_emr_name(emr->iType), emr->nSize);
2541 ret = (*callback)(hdc, ht, emr, emh->nHandles, (LPARAM)data);
2542 offset += emr->nSize;
2543 }
2544
2545 if (hdc && !is_meta_dc( hdc ))
2546 {
2547 SetStretchBltMode(hdc, old_stretchblt);
2548 SetPolyFillMode(hdc, old_polyfill);
2549 SetArcDirection(hdc, old_arcdir);
2550 SetROP2(hdc, old_rop2);
2551 SetTextAlign(hdc, old_align);
2552 SetBkColor(hdc, old_bk_color);
2553 SetTextColor(hdc, old_text_color);
2554
2555 /* restore DC */
2556 SelectObject(hdc, hBrush);
2557 SelectObject(hdc, hPen);
2561
2562 SetWorldTransform(hdc, &savedXform);
2563 if (savedMode)
2564 SetGraphicsMode(hdc, savedMode);
2565 SetMapMode(hdc, mapMode);
2566 SetWindowOrgEx(hdc, win_org.x, win_org.y, NULL);
2567 SetWindowExtEx(hdc, win_size.cx, win_size.cy, NULL);
2568 SetViewportOrgEx(hdc, vp_org.x, vp_org.y, NULL);
2569 SetViewportExtEx(hdc, vp_size.cx, vp_size.cy, NULL);
2570 }
2571
2572 for(i = 1; i < emh->nHandles; i++) /* Don't delete element 0 (hmf) */
2573 if( (ht->objectHandle)[i] )
2574 DeleteObject( (ht->objectHandle)[i] );
2575
2576 while (info->saved_state)
2577 {
2578 EMF_dc_state *state = info->saved_state;
2579 info->saved_state = info->saved_state->next;
2580 HeapFree( GetProcessHeap(), 0, state );
2581 }
2582 HeapFree( GetProcessHeap(), 0, info );
2583 return ret;
2584}
2585
2587 const ENHMETARECORD *emr,
2589{
2590 return PlayEnhMetaFileRecord(hdc, ht, emr, handles);
2591}
2592
2593/**************************************************************************
2594 * PlayEnhMetaFile (GDI32.@)
2595 *
2596 * Renders an enhanced metafile into a specified rectangle *lpRect
2597 * in device context hdc.
2598 *
2599 * RETURNS
2600 * Success: TRUE
2601 * Failure: FALSE
2602 */
2604 HDC hdc, /* [in] DC to render into */
2605 HENHMETAFILE hmf, /* [in] metafile to render */
2606 const RECT *lpRect /* [in] rectangle to place metafile inside */
2607 )
2608{
2609 return EnumEnhMetaFile(hdc, hmf, EMF_PlayEnhMetaFileCallback, NULL, lpRect);
2610}
2611
2612/*****************************************************************************
2613 * DeleteEnhMetaFile (GDI32.@)
2614 *
2615 * Deletes an enhanced metafile and frees the associated storage.
2616 */
2618{
2619 return EMF_Delete_HENHMETAFILE( hmf );
2620}
2621
2622/*****************************************************************************
2623 * CopyEnhMetaFileA (GDI32.@)
2624 *
2625 * Duplicate an enhanced metafile.
2626 *
2627 *
2628 */
2630 HENHMETAFILE hmfSrc,
2631 LPCSTR file)
2632{
2633 ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
2634 HENHMETAFILE hmfDst;
2635
2636 if(!emrSrc) return FALSE;
2637 if (!file) {
2638 emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
2639 memcpy( emrDst, emrSrc, emrSrc->nBytes );
2640 hmfDst = EMF_Create_HENHMETAFILE( emrDst, emrSrc->nBytes, FALSE );
2641 if (!hmfDst)
2642 HeapFree( GetProcessHeap(), 0, emrDst );
2643 } else {
2644 HANDLE hFile;
2645 DWORD w;
2647 NULL, CREATE_ALWAYS, 0, 0);
2648 WriteFile( hFile, emrSrc, emrSrc->nBytes, &w, NULL);
2649 CloseHandle( hFile );
2650 /* Reopen file for reading only, so that apps can share
2651 read access to the file while hmf is still valid */
2653 NULL, OPEN_EXISTING, 0, 0);
2655 ERR("Can't reopen emf for reading\n");
2656 return 0;
2657 }
2658 hmfDst = EMF_GetEnhMetaFile( hFile );
2659 CloseHandle( hFile );
2660 }
2661 return hmfDst;
2662}
2663
2664/*****************************************************************************
2665 * CopyEnhMetaFileW (GDI32.@)
2666 *
2667 * See CopyEnhMetaFileA.
2668 *
2669 *
2670 */
2672 HENHMETAFILE hmfSrc,
2673 LPCWSTR file)
2674{
2675 ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
2676 HENHMETAFILE hmfDst;
2677
2678 if(!emrSrc) return FALSE;
2679 if (!file) {
2680 emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
2681 memcpy( emrDst, emrSrc, emrSrc->nBytes );
2682 hmfDst = EMF_Create_HENHMETAFILE( emrDst, emrSrc->nBytes, FALSE );
2683 if (!hmfDst)
2684 HeapFree( GetProcessHeap(), 0, emrDst );
2685 } else {
2686 HANDLE hFile;
2687 DWORD w;
2689 NULL, CREATE_ALWAYS, 0, 0);
2690 WriteFile( hFile, emrSrc, emrSrc->nBytes, &w, NULL);
2691 CloseHandle( hFile );
2692 /* Reopen file for reading only, so that apps can share
2693 read access to the file while hmf is still valid */
2695 NULL, OPEN_EXISTING, 0, 0);
2697 ERR("Can't reopen emf for reading\n");
2698 return 0;
2699 }
2700 hmfDst = EMF_GetEnhMetaFile( hFile );
2701 CloseHandle( hFile );
2702 }
2703 return hmfDst;
2704}
2705
2706
2707/* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */
2709{
2713
2714/***************************************************************
2715 * Find the EMR_EOF record and then use it to find the
2716 * palette entries for this enhanced metafile.
2717 * The lpData is actually a pointer to an EMF_PaletteCopy struct
2718 * which contains the max number of elements to copy and where
2719 * to copy them to.
2720 *
2721 * NOTE: To be used by GetEnhMetaFilePaletteEntries only!
2722 */
2724 HANDLETABLE *b,
2725 const ENHMETARECORD *lpEMR,
2726 INT c,
2727 LPARAM lpData )
2728{
2729
2730 if ( lpEMR->iType == EMR_EOF )
2731 {
2732 const EMREOF *lpEof = (const EMREOF *)lpEMR;
2734 DWORD dwNumPalToCopy = min( lpEof->nPalEntries, info->cEntries );
2735
2736 TRACE( "copying 0x%08x palettes\n", dwNumPalToCopy );
2737
2738 memcpy( info->lpPe, (LPCSTR)lpEof + lpEof->offPalEntries,
2739 sizeof( *(info->lpPe) ) * dwNumPalToCopy );
2740
2741 /* Update the passed data as a return code */
2742 info->lpPe = NULL; /* Palettes were copied! */
2743 info->cEntries = dwNumPalToCopy;
2744
2745 return FALSE; /* That's all we need */
2746 }
2747
2748 return TRUE;
2749}
2750
2751/*****************************************************************************
2752 * GetEnhMetaFilePaletteEntries (GDI32.@)
2753 *
2754 * Copy the palette and report size
2755 *
2756 * BUGS: Error codes (SetLastError) are not set on failures
2757 */
2759 UINT cEntries,
2760 LPPALETTEENTRY lpPe )
2761{
2762 ENHMETAHEADER* enhHeader = EMF_GetEnhMetaHeader( hEmf );
2763 EMF_PaletteCopy infoForCallBack;
2764
2765 TRACE( "(%p,%d,%p)\n", hEmf, cEntries, lpPe );
2766
2767 if (!enhHeader) return 0;
2768
2769 /* First check if there are any palettes associated with
2770 this metafile. */
2771 if ( enhHeader->nPalEntries == 0 ) return 0;
2772
2773 /* Is the user requesting the number of palettes? */
2774 if ( lpPe == NULL ) return enhHeader->nPalEntries;
2775
2776 /* Copy cEntries worth of PALETTEENTRY structs into the buffer */
2777 infoForCallBack.cEntries = cEntries;
2778 infoForCallBack.lpPe = lpPe;
2779
2780 if ( !EnumEnhMetaFile( 0, hEmf, cbEnhPaletteCopy,
2781 &infoForCallBack, 0 ) )
2782 return GDI_ERROR;
2783
2784 /* Verify that the callback executed correctly */
2785 if ( infoForCallBack.lpPe != NULL )
2786 {
2787 /* Callback proc had error! */
2788 ERR( "cbEnhPaletteCopy didn't execute correctly\n" );
2789 return GDI_ERROR;
2790 }
2791
2792 return infoForCallBack.cEntries;
2793}
2794
2795/******************************************************************
2796 * extract_emf_from_comment
2797 *
2798 * If the WMF was created by GetWinMetaFileBits, then extract the
2799 * original EMF that is stored in MFCOMMENT chunks.
2800 */
2801static HENHMETAFILE extract_emf_from_comment( const BYTE *buf, UINT mf_size )
2802{
2803 METAHEADER *mh = (METAHEADER *)buf;
2804 METARECORD *mr;
2806 WORD checksum = 0;
2807 DWORD size = 0, remaining, chunks;
2808 BYTE *emf_bits = NULL, *ptr;
2809 UINT offset;
2810 HENHMETAFILE emf = NULL;
2811
2812 if (mf_size < sizeof(*mh)) return NULL;
2813
2814 for (offset = mh->mtHeaderSize * 2; offset < mf_size; offset += (mr->rdSize * 2))
2815 {
2816 mr = (METARECORD *)((char *)mh + offset);
2817 chunk = (emf_in_wmf_comment *)(mr->rdParm + 2);
2818
2819 if (mr->rdFunction != META_ESCAPE || mr->rdParm[0] != MFCOMMENT) goto done;
2820 if (chunk->magic != WMFC_MAGIC) goto done;
2821
2822 if (!emf_bits)
2823 {
2824 size = remaining = chunk->emf_size;
2825 chunks = chunk->num_chunks;
2826 emf_bits = ptr = HeapAlloc( GetProcessHeap(), 0, size );
2827 if (!emf_bits) goto done;
2828 }
2829 if (chunk->chunk_size > remaining) goto done;
2830 remaining -= chunk->chunk_size;
2831 if (chunk->remaining_size != remaining) goto done;
2832 memcpy( ptr, chunk->emf_data, chunk->chunk_size );
2833 ptr += chunk->chunk_size;
2834 if (--chunks == 0) break;
2835 }
2836
2837 for (offset = 0; offset < mf_size / 2; offset++)
2838 checksum += *((WORD *)buf + offset);
2839 if (checksum) goto done;
2840
2841 emf = SetEnhMetaFileBits( size, emf_bits );
2842
2843done:
2844 HeapFree( GetProcessHeap(), 0, emf_bits );
2845 return emf;
2846}
2847
2849{
2857
2858/******************************************************************
2859 * SetWinMetaFileBits (GDI32.@)
2860 *
2861 * Translate from old style to new style.
2862 *
2863 */
2864HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, const BYTE *lpbBuffer, HDC hdcRef,
2865 const METAFILEPICT *lpmfp)
2866{
2867 static const WCHAR szDisplayW[] = { 'D','I','S','P','L','A','Y','\0' };
2868 HMETAFILE hmf = NULL;
2869 HENHMETAFILE ret = NULL;
2870 HDC hdc = NULL, hdcdisp = NULL;
2871 RECT rc, *prcFrame = NULL;
2872 LONG mm, xExt, yExt;
2873 INT horzsize, vertsize, horzres, vertres;
2874
2875 TRACE("(%d, %p, %p, %p)\n", cbBuffer, lpbBuffer, hdcRef, lpmfp);
2876
2877 hmf = SetMetaFileBitsEx(cbBuffer, lpbBuffer);
2878 if(!hmf)
2879 {
2880 WARN("SetMetaFileBitsEx failed\n");
2881 return NULL;
2882 }
2883
2884 ret = extract_emf_from_comment( lpbBuffer, cbBuffer );
2885 if (ret) return ret;
2886
2887 if(!hdcRef)
2888 hdcRef = hdcdisp = CreateDCW(szDisplayW, NULL, NULL, NULL);
2889
2890 if (lpmfp)
2891 {
2892 TRACE("mm = %d %dx%d\n", lpmfp->mm, lpmfp->xExt, lpmfp->yExt);
2893
2894 mm = lpmfp->mm;
2895 xExt = lpmfp->xExt;
2896 yExt = lpmfp->yExt;
2897 }
2898 else
2899 {
2900 TRACE("lpmfp == NULL\n");
2901
2902 /* Use the whole device surface */
2903 mm = MM_ANISOTROPIC;
2904 xExt = 0;
2905 yExt = 0;
2906 }
2907
2908 if (mm == MM_ISOTROPIC || mm == MM_ANISOTROPIC)
2909 {
2910 if (xExt < 0 || yExt < 0)
2911 {
2912 /* Use the whole device surface */
2913 xExt = 0;
2914 yExt = 0;
2915 }
2916
2917 /* Use the x and y extents as the frame box */
2918 if (xExt && yExt)
2919 {
2920 rc.left = rc.top = 0;
2921 rc.right = xExt;
2922 rc.bottom = yExt;
2923 prcFrame = &rc;
2924 }
2925 }
2926
2927 if(!(hdc = CreateEnhMetaFileW(hdcRef, NULL, prcFrame, NULL)))
2928 {
2929 ERR("CreateEnhMetaFile failed\n");
2930 goto end;
2931 }
2932
2933 /*
2934 * Write the original METAFILE into the enhanced metafile.
2935 * It is encapsulated in a GDICOMMENT_WINDOWS_METAFILE record.
2936 */
2937 if (mm != MM_TEXT)
2938 {
2939 wmf_in_emf_comment *mfcomment;
2940 UINT mfcomment_size;
2941
2942 mfcomment_size = sizeof (*mfcomment) + cbBuffer;
2943 mfcomment = HeapAlloc(GetProcessHeap(), 0, mfcomment_size);
2944 if (mfcomment)
2945 {
2946 mfcomment->ident = GDICOMMENT_IDENTIFIER;
2948 mfcomment->nVersion = 0x00000300;
2949 mfcomment->nChecksum = 0; /* FIXME */
2950 mfcomment->fFlags = 0;
2951 mfcomment->cbWinMetaFile = cbBuffer;
2952 memcpy(&mfcomment[1], lpbBuffer, cbBuffer);
2953 GdiComment(hdc, mfcomment_size, (BYTE*) mfcomment);
2954 HeapFree(GetProcessHeap(), 0, mfcomment);
2955 }
2956 SetMapMode(hdc, mm);
2957 }
2958
2959
2960 horzsize = GetDeviceCaps(hdcRef, HORZSIZE);
2961 vertsize = GetDeviceCaps(hdcRef, VERTSIZE);
2962 horzres = GetDeviceCaps(hdcRef, HORZRES);
2963 vertres = GetDeviceCaps(hdcRef, VERTRES);
2964
2965 if (!xExt || !yExt)
2966 {
2967 /* Use the whole device surface */
2968 xExt = horzres;
2969 yExt = vertres;
2970 }
2971 else
2972 {
2973 xExt = MulDiv(xExt, horzres, 100 * horzsize);
2974 yExt = MulDiv(yExt, vertres, 100 * vertsize);
2975 }
2976
2977 /* set the initial viewport:window ratio as 1:1 */
2978 SetViewportExtEx(hdc, xExt, yExt, NULL);
2979 SetWindowExtEx(hdc, xExt, yExt, NULL);
2980
2981 PlayMetaFile(hdc, hmf);
2982
2984end:
2985 if (hdcdisp) DeleteDC(hdcdisp);
2986 DeleteMetaFile(hmf);
2987 return ret;
2988}
static int state
Definition: maze.c:121
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
struct _RGNDATAHEADER RGNDATAHEADER
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ALTERNATE
Definition: constants.h:278
HFONT hFont
Definition: main.c:53
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
Definition: arc.h:55
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define MapViewOfFile
Definition: compat.h:745
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define pt(x, y)
Definition: drawing.c:79
static VOID NTAPI BitBlt(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_reads_bytes_(Delta *Height) PUCHAR Buffer, _In_ ULONG BitsPerPixel, _In_ ULONG Delta)
Definition: common.c:49
#define RGB(r, g, b)
Definition: precomp.h:62
ULONG RGBQUAD
Definition: precomp.h:50
#define abs(i)
Definition: fconv.c:206
HANDLE NTAPI CreateFileMappingA(IN HANDLE hFile, IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, IN DWORD flProtect, IN DWORD dwMaximumSizeHigh, IN DWORD dwMaximumSizeLow, IN LPCSTR lpName)
Definition: filemap.c:23
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
pKey DeleteObject()
DWORD WINAPI SetLayout(_In_ HDC hdc, _In_ DWORD dwLayout)
Definition: coord.c:780
struct tagEMRESCAPE * PEMRESCAPE
struct tagEMRESCAPE * PEMRNAMEDESCAPE
#define WMFC_MAGIC
Definition: gdi_private.h:186
void * free_gdi_handle(HGDIOBJ handle) DECLSPEC_HIDDEN
Definition: rosglue.c:59
#define EMR_SETLINKEDUFI
Definition: gdi_private.h:193
static BOOL is_meta_dc(HDC hdc)
Definition: gdi_private.h:135
void GDI_ReleaseObj(HGDIOBJ) DECLSPEC_HIDDEN
Definition: rosglue.c:100
HGDIOBJ alloc_gdi_handle(void *obj, WORD type, const struct gdi_obj_funcs *funcs) DECLSPEC_HIDDEN
void * GDI_GetObjPtr(HGDIOBJ, WORD) DECLSPEC_HIDDEN
Definition: rosglue.c:66
#define DIB_PAL_MONO
Definition: gdi_private.h:196
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const struct newhuff ht[]
Definition: huffman.h:296
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
#define bits
Definition: infblock.c:15
#define debugstr_w
Definition: kernel32.h:32
GLint dx
Definition: linetemp.h:97
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define CREATE_ALWAYS
Definition: disk.h:72
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst, HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc, BLENDFUNCTION blendFunction)
HDC hdc
Definition: main.c:9
BOOL WINAPI GdiGradientFill(HDC hdc, TRIVERTEX *vert_array, ULONG nvert, void *grad_array, ULONG ngrad, ULONG mode)
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static IPrintDialogCallback callback
Definition: printdlg.c:326
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static HRGN hRgn
Definition: mapping.c:33
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
static const unsigned char enhmetafile[]
Definition: olepicture.c:149
#define min(a, b)
Definition: monoChain.cc:55
_In_ HANDLE hFile
Definition: mswsock.h:90
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
#define OBJ_PEN
Definition: objidl.idl:1409
#define OBJ_BRUSH
Definition: objidl.idl:1410
#define OBJ_FONT
Definition: objidl.idl:1414
#define OBJ_ENHMETAFILE
Definition: objidl.idl:1421
long LONG
Definition: pedump.c:60
BOOL Polygon(CONST PPOINT UnsafePoints, int Count, int polyFillMode)
Definition: polytest.cpp:730
#define TRACE(s)
Definition: solgame.cpp:4
XFORM world_transform
Definition: enhmetafile.c:531
struct EMF_dc_state * next
Definition: enhmetafile.c:540
ENHMETAHEADER * emh
Definition: enhmetafile.c:63
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
Definition: bl.h:1331
LIST_ENTRY ProcessLocksList
Definition: winbase.h:883
LONG y
Definition: windef.h:330
LONG x
Definition: windef.h:329
RECT rcl
Definition: wingdi.h:2557
LPCSTR lpstr
Definition: wingdi.h:2555
UINT uiFlags
Definition: wingdi.h:2556
int * pdx
Definition: wingdi.h:2558
UINT n
Definition: wingdi.h:2554
LPCWSTR lpstr
Definition: wingdi.h:2564
UINT uiFlags
Definition: wingdi.h:2565
RECT rcl
Definition: wingdi.h:2566
UINT n
Definition: wingdi.h:2563
int * pdx
Definition: wingdi.h:2567
RGNDATAHEADER rdh
Definition: axextend.idl:399
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
FLOAT eDy
Definition: wingdi.h:1726
FLOAT eM11
Definition: wingdi.h:1721
FLOAT eM21
Definition: wingdi.h:1723
FLOAT eM22
Definition: wingdi.h:1724
FLOAT eM12
Definition: wingdi.h:1722
FLOAT eDx
Definition: wingdi.h:1725
Definition: emfdc.c:45
const char * name
Definition: enhmetafile.c:69
DWORD type
Definition: enhmetafile.c:68
XFORM init_transform
Definition: enhmetafile.c:545
EMF_dc_state * saved_state
Definition: enhmetafile.c:548
EMF_dc_state state
Definition: enhmetafile.c:546
Definition: fci.c:127
LPPALETTEENTRY lpPe
Definition: enhmetafile.c:2711
XFORM xformSrc
Definition: wingdi.h:2266
DWORD offBitsSrc
Definition: wingdi.h:2271
DWORD cbBitsSrc
Definition: wingdi.h:2272
DWORD iUsageSrc
Definition: wingdi.h:2268
DWORD offBmiSrc
Definition: wingdi.h:2269
FLOAT eSweepAngle
Definition: wingdi.h:1712
FLOAT eStartAngle
Definition: wingdi.h:1711
DWORD nRadius
Definition: wingdi.h:1710
POINTL ptlCenter
Definition: wingdi.h:1709
POINTL ptlStart
Definition: wingdi.h:1717
RECTL rclBox
Definition: wingdi.h:1716
POINTL ptlEnd
Definition: wingdi.h:1718
LONG cyDest
Definition: wingdi.h:1734
DWORD dwRop
Definition: wingdi.h:1735
XFORM xformSrc
Definition: wingdi.h:1738
COLORREF crBkColorSrc
Definition: wingdi.h:1739
LONG ySrc
Definition: wingdi.h:1737
LONG xSrc
Definition: wingdi.h:1736
RECTL rclBounds
Definition: wingdi.h:1730
DWORD offBitsSrc
Definition: wingdi.h:1743
LONG xDest
Definition: wingdi.h:1731
DWORD iUsageSrc
Definition: wingdi.h:1740
LONG cxDest
Definition: wingdi.h:1733
DWORD offBmiSrc
Definition: wingdi.h:1741
LONG yDest
Definition: wingdi.h:1732
LOGCOLORSPACEA lcs
Definition: wingdi.h:1799
LOGPALETTE lgpl
Definition: wingdi.h:1842
LOGPEN lopn
Definition: wingdi.h:1852
RECTL rclBox
Definition: wingdi.h:1856
DWORD offPalEntries
Definition: wingdi.h:1861
DWORD nPalEntries
Definition: wingdi.h:1860
BYTE Data[1]
Definition: gdi_private.h:89
EXTLOGPEN elp
Definition: wingdi.h:1957
COLORREF crColor
Definition: wingdi.h:1962
DWORD iGraphicsMode
Definition: wingdi.h:1982
EMRTEXT emrtext
Definition: wingdi.h:1985
BYTE RgnData[1]
Definition: wingdi.h:1996
DWORD cbRgnData
Definition: wingdi.h:1994
DWORD ihBrush
Definition: wingdi.h:1995
SIZEL szlStroke
Definition: wingdi.h:2018
DWORD ihBrush
Definition: wingdi.h:2017
DWORD cbRgnData
Definition: wingdi.h:2016
BYTE RgnData[1]
Definition: wingdi.h:2019
BYTE Data[1]
Definition: wingdi.h:2024
TRIVERTEX Ver[1]
Definition: wingdi.h:2797
BYTE RgnData[1]
Definition: wingdi.h:2030
DWORD cbRgnData
Definition: wingdi.h:2029
POINTL ptl
Definition: wingdi.h:2034
RECTL rclBounds
Definition: wingdi.h:2038
DWORD offBitsSrc
Definition: wingdi.h:2051
DWORD offBitsMask
Definition: wingdi.h:2058
DWORD offBmiSrc
Definition: wingdi.h:2049
LONG yMask
Definition: wingdi.h:2054
COLORREF crBkColorSrc
Definition: wingdi.h:2047
DWORD iUsageMask
Definition: wingdi.h:2055
LONG yDest
Definition: wingdi.h:2040
LONG xMask
Definition: wingdi.h:2053
DWORD dwRop
Definition: wingdi.h:2043
DWORD iUsageSrc
Definition: wingdi.h:2048
LONG cyDest
Definition: wingdi.h:2042
LONG xDest
Definition: wingdi.h:2039
XFORM xformSrc
Definition: wingdi.h:2046
DWORD offBmiMask
Definition: wingdi.h:2056
LONG cxDest
Definition: wingdi.h:2041
PIXELFORMATDESCRIPTOR pfd
Definition: wingdi.h:2601
DWORD offBmiMask
Definition: wingdi.h:2088
LONG xMask
Definition: wingdi.h:2085
LONG cySrc
Definition: wingdi.h:2077
DWORD offBitsSrc
Definition: wingdi.h:2083
RECTL rclBounds
Definition: wingdi.h:2072
DWORD iUsageSrc
Definition: wingdi.h:2080
COLORREF crBkColorSrc
Definition: wingdi.h:2079
XFORM xformSrc
Definition: wingdi.h:2078
LONG xSrc
Definition: wingdi.h:2074
DWORD offBmiSrc
Definition: wingdi.h:2081
LONG cxSrc
Definition: wingdi.h:2076
POINTL aptlDest[3]
Definition: wingdi.h:2073
LONG yMask
Definition: wingdi.h:2086
DWORD offBitsMask
Definition: wingdi.h:2090
DWORD iUsageMask
Definition: wingdi.h:2087
LONG ySrc
Definition: wingdi.h:2075
POINTS apts[1]
Definition: wingdi.h:2104
POINTL aptl[1]
Definition: wingdi.h:2097
DWORD cptl
Definition: wingdi.h:2096
BYTE abTypes[1]
Definition: wingdi.h:2098
POINTS apts[1]
Definition: wingdi.h:2117
DWORD cptl
Definition: wingdi.h:2110
POINTL aptl[1]
Definition: wingdi.h:2111
DWORD aPolyCounts[1]
Definition: wingdi.h:2132
DWORD aPolyCounts[1]
Definition: wingdi.h:2124
DWORD iGraphicsMode
Definition: wingdi.h:2138
EMRTEXT aemrtext[1]
Definition: wingdi.h:2142
LONG iRelative
Definition: wingdi.h:2151
RECTL rclBox
Definition: wingdi.h:2155
SIZEL szlCorner
Definition: wingdi.h:2156
COLORADJUSTMENT ColorAdjustment
Definition: wingdi.h:2185
PALETTEENTRY aPalEntries[1]
Definition: wingdi.h:2217
POINTL ptlPixel
Definition: wingdi.h:2221
COLORREF crColor
Definition: wingdi.h:2222
COLORREF crColor
Definition: wingdi.h:2181
XFORM xformSrc
Definition: wingdi.h:2246
DWORD iUsageSrc
Definition: wingdi.h:2248
DWORD offBitsSrc
Definition: wingdi.h:2251
RECTL rclBounds
Definition: wingdi.h:2238
DWORD offBmiSrc
Definition: wingdi.h:2249
COLORREF crBkColorSrc
Definition: wingdi.h:2247
DWORD fOptions
Definition: wingdi.h:1975
DWORD offDx
Definition: wingdi.h:1977
DWORD nChars
Definition: wingdi.h:1973
RECTL rcl
Definition: wingdi.h:1976
POINTL ptlReference
Definition: wingdi.h:1972
DWORD offString
Definition: wingdi.h:1974
RECTL rclFrame
Definition: wingdi.h:2323
SIZEL szlDevice
Definition: wingdi.h:2333
DWORD nDescription
Definition: wingdi.h:2330
DWORD dSignature
Definition: wingdi.h:2324
SIZEL szlMillimeters
Definition: wingdi.h:2334
DWORD nPalEntries
Definition: wingdi.h:2332
DWORD offDescription
Definition: wingdi.h:2331
LOGFONTW elfLogFont
Definition: wingdi.h:1925
DWORD elpNumEntries
Definition: wingdi.h:1947
DWORD elpWidth
Definition: wingdi.h:1943
DWORD elpPenStyle
Definition: wingdi.h:1942
UINT elpBrushStyle
Definition: wingdi.h:1944
DWORD elpStyleEntry[1]
Definition: wingdi.h:1948
ULONG_PTR elpHatch
Definition: wingdi.h:1946
COLORREF elpColor
Definition: wingdi.h:1945
HGDIOBJ objectHandle[1]
Definition: wingdi.h:2355
ULONG lbHatch
Definition: wingdi.h:1755
UINT lbStyle
Definition: wingdi.h:1753
COLORREF lbColor
Definition: wingdi.h:1754
UINT lbStyle
Definition: wingdi.h:1747
ULONG_PTR lbHatch
Definition: wingdi.h:1749
COLORREF lbColor
Definition: wingdi.h:1748
WORD mtHeaderSize
Definition: wingdi.h:2311
DWORD rdSize
Definition: wingdi.h:2345
WORD rdParm[1]
Definition: wingdi.h:2347
WORD rdFunction
Definition: wingdi.h:2346
SHORT y
Definition: windef.h:343
SHORT x
Definition: windef.h:342
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
Definition: cmds.c:130
#define DWORD_PTR
Definition: treelist.c:76
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
static EFI_HANDLE * handles
Definition: uefidisk.c:62
int ret
#define RECT
Definition: precomp.h:26
INT WINAPI NamedEscape(HDC hdc, PWCHAR pDriver, INT iEsc, INT cjIn, LPSTR pjIn, INT cjOut, LPSTR pjOut)
Definition: misc.c:229
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
static CRITICAL_SECTION enhmetafile_cs
Definition: enhmetafile.c:52
UINT WINAPI GetEnhMetaFileBits(HENHMETAFILE hmf, UINT bufsize, LPBYTE buf)
Definition: enhmetafile.c:509
HENHMETAFILE WINAPI GetEnhMetaFileW(LPCWSTR lpszMetaFile)
Definition: enhmetafile.c:389
HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, const BYTE *lpbBuffer, HDC hdcRef, const METAFILEPICT *lpmfp)
Definition: enhmetafile.c:2864
struct tagEMF_PaletteCopy EMF_PaletteCopy
static INT CALLBACK cbEnhPaletteCopy(HDC a, HANDLETABLE *b, const ENHMETARECORD *lpEMR, INT c, LPARAM lpData)
Definition: enhmetafile.c:2723
UINT WINAPI GetEnhMetaFileDescriptionW(HENHMETAFILE hmf, UINT size, LPWSTR buf)
Definition: enhmetafile.c:473
#define ENUM_GET_PRIVATE_DATA(ht)
Definition: enhmetafile.c:551
HENHMETAFILE WINAPI CopyEnhMetaFileA(HENHMETAFILE hmfSrc, LPCSTR file)
Definition: enhmetafile.c:2629
static void EMF_RestoreDC(enum_emh_data *info, INT level)
Definition: enhmetafile.c:582
#define X(p)
static void EMF_SaveDC(enum_emh_data *info)
Definition: enhmetafile.c:599
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: enhmetafile.c:53
static HENHMETAFILE extract_emf_from_comment(const BYTE *buf, UINT mf_size)
Definition: enhmetafile.c:2801
UINT WINAPI GetEnhMetaFileDescriptionA(HENHMETAFILE hmf, UINT size, LPSTR buf)
Definition: enhmetafile.c:441
static BOOL emr_produces_output(int type)
Definition: enhmetafile.c:703
static void EMF_FixIsotropic(HDC hdc, enum_emh_data *info)
Definition: enhmetafile.c:673
static HENHMETAFILE EMF_GetEnhMetaFile(HANDLE hFile)
Definition: enhmetafile.c:341
static const struct emr_name emr_names[]
HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
Definition: enhmetafile.c:494
static BOOL EMF_Delete_HENHMETAFILE(HENHMETAFILE hmf)
Definition: enhmetafile.c:295
static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info)
Definition: enhmetafile.c:559
static const char * get_emr_name(DWORD type)
Definition: enhmetafile.c:199
#define IS_WIN9X()
Definition: enhmetafile.c:557
static INT CALLBACK EMF_PlayEnhMetaFileCallback(HDC hdc, HANDLETABLE *ht, const ENHMETARECORD *emr, INT handles, LPARAM data)
Definition: enhmetafile.c:2586
#define HEIGHT(rect)
Definition: enhmetafile.c:555
static BOOL is_dib_monochrome(const BITMAPINFO *info)
Definition: enhmetafile.c:220
BOOL WINAPI EnumEnhMetaFile(HDC hdc, HENHMETAFILE hmf, ENHMFENUMPROC callback, LPVOID data, const RECT *lpRect)
Definition: enhmetafile.c:2371
static ENHMETAHEADER * EMF_GetEnhMetaHeader(HENHMETAFILE hmf)
Definition: enhmetafile.c:320
HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, DWORD filesize, BOOL on_disk)
Definition: enhmetafile.c:259
static void EMF_SetMapMode(HDC hdc, enum_emh_data *info)
Definition: enhmetafile.c:612
#define WIDTH(rect)
Definition: enhmetafile.c:554
BOOL WINAPI PlayEnhMetaFileRecord(HDC hdc, LPHANDLETABLE handletable, const ENHMETARECORD *mr, UINT handles)
Definition: enhmetafile.c:777
UINT WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE hEmf, UINT cEntries, LPPALETTEENTRY lpPe)
Definition: enhmetafile.c:2758
HENHMETAFILE WINAPI GetEnhMetaFileA(LPCSTR lpszMetaFile)
Definition: enhmetafile.c:368
HENHMETAFILE WINAPI CopyEnhMetaFileW(HENHMETAFILE hmfSrc, LPCWSTR file)
Definition: enhmetafile.c:2671
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
_In_ ULONG _In_ ULONG rgb
Definition: winddi.h:3521
_Inout_ PERBANDINFO * pbi
Definition: winddi.h:3917
_In_ LONG iPixelFormat
Definition: winddi.h:3488
LONG_PTR LPARAM
Definition: windef.h:208
DWORD COLORREF
Definition: windef.h:300
#define WINAPI
Definition: msvc.h:6
#define ERROR_INVALID_DATA
Definition: winerror.h:116
BOOL WINAPI DeleteMetaFile(_In_ HMETAFILE)
int WINAPI SetMapMode(_In_ HDC, _In_ int)
BOOL WINAPI ArcTo(_In_ HDC hdc, _In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom, _In_ INT xRadial1, _In_ INT yRadial1, _In_ INT xRadial2, _In_ INT yRadial2)
Definition: arc.c:79
HBRUSH WINAPI CreateBrushIndirect(_In_ const LOGBRUSH *plb)
#define EMR_INTERSECTCLIPRECT
Definition: wingdi.h:104
#define EMR_POLYPOLYLINE
Definition: wingdi.h:81
BOOL WINAPI DeleteColorSpace(_In_ HCOLORSPACE)
#define EMR_STRETCHBLT
Definition: wingdi.h:150
#define EMR_SAVEDC
Definition: wingdi.h:107
#define GDICOMMENT_WINDOWS_METAFILE
Definition: wingdi.h:662
#define EMR_POLYTEXTOUTW
Definition: wingdi.h:170
#define EMR_FRAMERGN
Definition: wingdi.h:145
#define EMR_SELECTCLIPPATH
Definition: wingdi.h:141
#define EMR_SETWINDOWEXTEX
Definition: wingdi.h:83
#define EMR_SETTEXTCOLOR
Definition: wingdi.h:98
#define EMR_SETVIEWPORTEXTEX
Definition: wingdi.h:85
int WINAPI ChoosePixelFormat(_In_ HDC hdc, _In_ const PIXELFORMATDESCRIPTOR *ppfd)
BOOL WINAPI Chord(_In_ HDC hdc, _In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom, _In_ INT xRadial1, _In_ INT yRadial1, _In_ INT xRadial2, _In_ INT yRadial2)
Definition: arc.c:119
int WINAPI SetDIBitsToDevice(_In_ HDC, _In_ int, _In_ int, _In_ DWORD, _In_ DWORD, _In_ int, _In_ int, _In_ UINT, _In_ UINT, _In_ CONST VOID *, _In_ CONST BITMAPINFO *, _In_ UINT)
#define HORZRES
Definition: wingdi.h:716
BOOL WINAPI PolyBezier(_In_ HDC hdc, _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt)
Definition: painting.c:263
#define MM_HIENGLISH
Definition: wingdi.h:868
#define EMR_EXTTEXTOUTA
Definition: wingdi.h:156
#define EMR_SETTEXTALIGN
Definition: wingdi.h:96
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define MWT_LEFTMULTIPLY
Definition: wingdi.h:945
BOOL WINAPI Polyline(_In_ HDC hdc, _In_reads_(cpt) const POINT *apt, _In_ int cpt)
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
BOOL WINAPI Ellipse(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
#define EMR_POLYBEZIER16
Definition: wingdi.h:158
HCOLORSPACE WINAPI SetColorSpace(_In_ HDC, _In_ HCOLORSPACE)
#define EMR_CREATEPALETTE
Definition: wingdi.h:123
UINT WINAPI RealizePalette(_In_ HDC)
Definition: palette.c:138
#define EMR_BITBLT
Definition: wingdi.h:149
BOOL WINAPI DeleteEnhMetaFile(_In_opt_ HENHMETAFILE)
BOOL WINAPI PolylineTo(_In_ HDC hdc, _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt)
Definition: painting.c:354
#define