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