[GDI32] Meta File Fix Ups
[reactos.git] / win32ss / gdi / gdi32 / objects / metafile.c
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 }