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