xref: /reactos/win32ss/gdi/gdi32/objects/metafile.c (revision 3e1f4074)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            win32ss/gdi/gdi32/objects/metafile.c
5  * PURPOSE:         metafile and enhanced metafile support
6  * PROGRAMMERS:     Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7  */
8 #include <precomp.h>
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 /* FUNCTIONS *****************************************************************/
14 
15 /*
16  * @implemented
17  */
18 BOOL
19 WINAPI
20 GdiIsPlayMetafileDC(HDC hdc)
21 {
22     PDC_ATTR pdcattr = GdiGetDcAttr(hdc);
23 
24     if ( pdcattr )
25     {
26         return !!( pdcattr->ulDirty_ & DC_PLAYMETAFILE );
27     }
28     return FALSE;
29 }
30 
31 /*
32  * @implemented
33  */
34 BOOL
35 WINAPI
36 GdiIsMetaFileDC(HDC hdc)
37 {
38     ULONG ulObjType;
39 
40     ulObjType = GDI_HANDLE_GET_TYPE(hdc);
41     if (ulObjType == GDILoObjType_LO_METADC16_TYPE)
42     {
43         return TRUE;
44     }
45 
46     if (ulObjType == GDILoObjType_LO_ALTDC_TYPE)
47     {
48         PLDC pLDC = GdiGetLDC(hdc);
49         if ( !pLDC )
50         {
51             SetLastError(ERROR_INVALID_HANDLE);
52             return FALSE;
53         }
54         return !!( pLDC->iType == LDC_EMFLDC );
55     }
56 
57     return FALSE;
58 }
59 
60 /*
61  * @implemented
62  */
63 BOOL
64 WINAPI
65 GdiIsMetaPrintDC(HDC hdc)
66 {
67     ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
68 
69     if ( hType != GDILoObjType_LO_DC_TYPE )
70     {
71         if ( hType == GDILoObjType_LO_METADC16_TYPE )
72             return FALSE;
73         else
74         {
75             PLDC pLDC = GdiGetLDC(hdc);
76             if ( !pLDC )
77             {
78                 SetLastError(ERROR_INVALID_HANDLE);
79                 return FALSE;
80             }
81             return !!( pLDC->Flags & LDC_META_PRINT );
82         }
83     }
84     return FALSE;
85 }
86 
87 // NOTE: I wanna use GdiCreateLocalMetaFilePict and GdiConvertMetaFilePict
88 //       functions for clipboard data conversion. --- katahiromz
89 
90 /*
91  * @implemented
92  */
93 HGLOBAL
94 WINAPI
95 GdiCreateLocalMetaFilePict(HANDLE hmo)
96 {
97     HGLOBAL         hMetaFilePict;
98     METAFILEPICT *  pInfo;
99     HMETAFILE       hMF = NULL;
100     BYTE *          Buffer = NULL;
101     BYTE *          BufNew = NULL;
102     HDC             hDC = NULL;
103     UINT            nSize, cSize;
104     DWORD           iType;
105 
106     // NOTE: On Win32, there is no difference between the local heap and
107     //       the global heap. GlobalAlloc and LocalAlloc have same effect.
108 
109     // allocate for METAFILEPICT
110     hMetaFilePict = GlobalAlloc(GHND | GMEM_SHARE, sizeof(METAFILEPICT));
111     pInfo = (METAFILEPICT *)GlobalLock(hMetaFilePict);
112     if (pInfo == NULL)
113         goto Exit;
114 
115     nSize = NtGdiGetServerMetaFileBits( hmo, 0, NULL, NULL, NULL, NULL, NULL );
116 
117     // allocate buffer
118     Buffer = (BYTE *)LocalAlloc(LPTR, nSize);
119     if (Buffer == NULL)
120         goto Exit;
121 
122     // store to buffer
123     nSize = NtGdiGetServerMetaFileBits( hmo, nSize, Buffer, &iType, (PDWORD)&pInfo->mm, (PDWORD)&pInfo->xExt, (PDWORD)&pInfo->yExt );
124     if (nSize == 0)
125         goto Exit;
126 
127     if ( iType == GDITAG_TYPE_EMF ) // handle conversion to MFP
128     {
129         static const WCHAR szDisplayW[] = { 'D','I','S','P','L','A','Y','\0' };
130         HENHMETAFILE hEMF;
131         ENHMETAHEADER emh;
132 
133         hEMF = SetEnhMetaFileBits(nSize, Buffer);
134         if (hEMF == NULL)
135             goto Exit;
136 
137         if (!GetEnhMetaFileHeader( hEMF, sizeof(emh), &emh ))
138         {
139             DeleteEnhMetaFile(hEMF);
140             goto Exit;
141         }
142 
143         pInfo->mm   = MM_ANISOTROPIC; // wine uses MM_ISOTROPIC.
144         pInfo->xExt = emh.rclFrame.right   - emh.rclFrame.left; // Width
145         pInfo->yExt = emh.rclFrame.bottom  - emh.rclFrame.top;  // Height
146 
147         hDC = CreateDCW(szDisplayW, NULL, NULL, NULL);
148         if (hDC)
149         {
150             cSize = GetWinMetaFileBits( hEMF, 0, NULL, MM_ANISOTROPIC, hDC );
151             if (cSize)
152             {
153                 BufNew = (BYTE *)LocalAlloc(LPTR, cSize);
154                 if (BufNew)
155                 {
156                     nSize = GetWinMetaFileBits( hEMF, cSize, (LPBYTE)BufNew, MM_ANISOTROPIC, hDC );
157                     if (nSize == cSize)
158                     {
159                         if (Buffer) LocalFree(Buffer);
160                         Buffer = BufNew;
161                     }
162                 }
163             }
164             DeleteDC(hDC);
165         }
166         DeleteEnhMetaFile(hEMF);
167 
168         if (Buffer != BufNew)
169             goto Exit;
170     }
171 
172     // create metafile from buffer
173     hMF = SetMetaFileBitsEx(nSize, Buffer);
174     if (hMF == NULL)
175         goto Exit;
176 
177     // set metafile handle
178     pInfo->hMF = hMF;
179 
180 Exit:
181     // clean up
182     if (Buffer)
183         LocalFree(Buffer);
184     if (pInfo)
185         GlobalUnlock(hMetaFilePict);
186     if (hMF == NULL)
187     {
188         // failure
189         GlobalFree(hMetaFilePict);
190         hMetaFilePict = NULL;
191     }
192 
193     return hMetaFilePict;   // success if non-NULL
194 }
195 
196 /*
197  * @implemented
198  */
199 HANDLE
200 WINAPI
201 GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
202 {
203     HMETAFILE       hMF;
204     UINT            nSize;
205     HANDLE          hmo    = NULL;
206     BYTE *          Buffer = NULL;
207     METAFILEPICT *  pInfo  = NULL;
208 
209     // get METAFILEPICT pointer
210     pInfo = (METAFILEPICT *)GlobalLock(hMetaFilePict);
211     if (pInfo == NULL)
212         goto Exit;
213 
214     // get metafile handle
215     hMF = pInfo->hMF;
216 
217     // get size of buffer
218     nSize = GetMetaFileBitsEx(hMF, 0, NULL);
219     if (nSize == 0)
220         goto Exit;
221 
222     // allocate buffer
223     Buffer = (BYTE *)LocalAlloc(LPTR, nSize);
224     if (Buffer == NULL)
225         goto Exit;
226 
227     // store to buffer
228     nSize = GetMetaFileBitsEx(hMF, nSize, Buffer);
229     if (nSize == 0)
230         goto Exit;
231 
232     hmo = NtGdiCreateServerMetaFile( GDITAG_TYPE_MFP, nSize, Buffer, pInfo->mm, pInfo->xExt, pInfo->yExt);
233 
234 Exit:
235     // clean up
236     if (pInfo)
237         GlobalUnlock(hMetaFilePict);
238     if (Buffer)
239         LocalFree(Buffer);
240     return hmo;    // success if non-NULL
241 }
242