aboutsummaryrefslogtreecommitdiff
path: root/smelt/sdl/CxImage/ximawmf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'smelt/sdl/CxImage/ximawmf.cpp')
-rw-r--r--smelt/sdl/CxImage/ximawmf.cpp483
1 files changed, 0 insertions, 483 deletions
diff --git a/smelt/sdl/CxImage/ximawmf.cpp b/smelt/sdl/CxImage/ximawmf.cpp
deleted file mode 100644
index a1057f5..0000000
--- a/smelt/sdl/CxImage/ximawmf.cpp
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
-*********************************************************************
- * File: ximawmf.cpp
- * Purpose: Windows Metafile Class Loader and Writer
- * Author: Volker Horch - vhorch@gmx.de
- * created: 13-Jun-2002
- *
- * Note: If the code below works, i wrote it.
- * If it doesn't work, i don't know who wrote it.
-*********************************************************************
- */
-
-/*
-*********************************************************************
- Note by Author:
-*********************************************************************
-
- Metafile Formats:
- =================
-
- There are 2 kinds of Windows Metafiles:
- - Standard Windows Metafile
- - Placeable Windows Metafile
-
- A StandardWindows Metafile looks like:
- - Metafile Header (MEATAHEADER)
- - Metafile Records
-
- A Placeable Metafile looks like:
- - Aldus Header (METAFILEHEADER)
- - Metafile Header (METAHEADER)
- - Metafile Records
-
- The "Metafile Header" and the "Metafile Records" are the same
- for both formats. However, the Standard Metafile does not contain any
- information about the original dimensions or x/y ratio of the Metafile.
-
- I decided, to allow only placeable Metafiles here. If you also want to
- enable Standard Metafiles, you will have to guess the dimensions of
- the image.
-
-*********************************************************************
- Limitations: see ximawmf.h
- you may configure some stuff there
-*********************************************************************
-*/
-
-#include "ximawmf.h"
-
-#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
-
-////////////////////////////////////////////////////////////////////////////////
-#if CXIMAGE_SUPPORT_DECODE
-////////////////////////////////////////////////////////////////////////////////
-bool CxImageWMF::Decode(CxFile *hFile, int32_t nForceWidth, int32_t nForceHeight)
-{
- if (hFile == NULL) return false;
-
- HENHMETAFILE hMeta;
- HDC hDC;
- int32_t cx,cy;
-
- //save the current position of the file
- int32_t pos = hFile->Tell();
-
- // Read the Metafile and convert to an Enhanced Metafile
- METAFILEHEADER mfh;
- hMeta = ConvertWmfFiletoEmf(hFile, &mfh);
- if (hMeta) { // ok, it's a WMF
-
-/////////////////////////////////////////////////////////////////////
-// We use the original WMF size information, because conversion to
-// EMF adjusts the Metafile to Full Screen or does not set rclBounds at all
-// ENHMETAHEADER emh;
-// uint32_t uRet;
-// uRet = GetEnhMetaFileHeader(hMeta, // handle of enhanced metafile
-// sizeof(ENHMETAHEADER), // size of buffer, in bytes
-// &emh); // address of buffer to receive data
-// if (!uRet){
-// DeleteEnhMetaFile(hMeta);
-// return false;
-// }
-// // calculate size
-// cx = emh.rclBounds.right - emh.rclBounds.left;
-// cy = emh.rclBounds.bottom - emh.rclBounds.top;
-/////////////////////////////////////////////////////////////////////
-
- // calculate size
- // scale the metafile (pixels/inch of metafile => pixels/inch of display)
- // mfh.inch already checked to be <> 0
-
- hDC = ::GetDC(0);
- int32_t cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);
- int32_t cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);
- ::ReleaseDC(0, hDC);
-
- cx = (mfh.inch/2 + (mfh.bbox.right - mfh.bbox.left) * cx1) / mfh.inch;
- cy = (mfh.inch/2 + (mfh.bbox.bottom - mfh.bbox.top) * cy1) / mfh.inch;
-
- } else { // maybe it's an EMF...
-
- hFile->Seek(pos,SEEK_SET);
-
- ENHMETAHEADER emh;
- hMeta = ConvertEmfFiletoEmf(hFile, &emh);
-
- if (!hMeta){
- strcpy(info.szLastError,"corrupted WMF");
- return false; // definitively give up
- }
-
- // ok, it's an EMF; calculate canvas size
- cx = emh.rclBounds.right - emh.rclBounds.left;
- cy = emh.rclBounds.bottom - emh.rclBounds.top;
-
- // alternative methods, sometime not so reliable... [DP]
- //cx = emh.szlDevice.cx;
- //cy = emh.szlDevice.cy;
- //
- //hDC = ::GetDC(0);
- //float hscale = (float)GetDeviceCaps(hDC, HORZRES)/(100.0f * GetDeviceCaps(hDC, HORZSIZE));
- //float vscale = (float)GetDeviceCaps(hDC, VERTRES)/(100.0f * GetDeviceCaps(hDC, VERTSIZE));
- //::ReleaseDC(0, hDC);
- //cx = (int32_t)((emh.rclFrame.right - emh.rclFrame.left) * hscale);
- //cy = (int32_t)((emh.rclFrame.bottom - emh.rclFrame.top) * vscale);
- }
-
- if (info.nEscape == -1) { // Check if cancelled
- head.biWidth = cx;
- head.biHeight= cy;
- info.dwType = CXIMAGE_FORMAT_WMF;
- DeleteEnhMetaFile(hMeta);
- strcpy(info.szLastError,"output dimensions returned");
- return true;
- }
-
- if (!cx || !cy) {
- DeleteEnhMetaFile(hMeta);
- strcpy(info.szLastError,"empty WMF");
- return false;
- }
-
- if (nForceWidth) cx=nForceWidth;
- if (nForceHeight) cy=nForceHeight;
- ShrinkMetafile(cx, cy); // !! Otherwise Bitmap may have bombastic size
-
- HDC hDC0 = ::GetDC(0); // DC of screen
- HBITMAP hBitmap = CreateCompatibleBitmap(hDC0, cx, cy); // has # colors of display
- hDC = CreateCompatibleDC(hDC0); // memory dc compatible with screen
- ::ReleaseDC(0, hDC0); // don't need anymore. get rid of it.
-
- if (hDC){
- if (hBitmap){
- RECT rc = {0,0,cx,cy};
- int32_t bpp = ::GetDeviceCaps(hDC, BITSPIXEL);
-
- HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);
-
- // clear out the entire bitmap with windows background
- // because the MetaFile may not contain background information
- uint32_t dwBack = XMF_COLOR_BACK;
-#if XMF_SUPPORT_TRANSPARENCY
- if (bpp == 24) dwBack = XMF_COLOR_TRANSPARENT;
-#endif
- uint32_t OldColor = SetBkColor(hDC, dwBack);
- ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
- SetBkColor(hDC, OldColor);
-
- //retrieves optional palette entries from the specified enhanced metafile
- PLOGPALETTE plogPal;
- PBYTE pjTmp;
- HPALETTE hPal;
- int32_t iEntries = GetEnhMetaFilePaletteEntries(hMeta, 0, NULL);
- if (iEntries) {
- if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
- sizeof(uint32_t) + sizeof(PALETTEENTRY)*iEntries )) == NULL) {
- DeleteObject(hBitmap);
- DeleteDC(hDC);
- DeleteEnhMetaFile(hMeta);
- strcpy(info.szLastError,"Cancelled");
- return false;
- }
-
- plogPal->palVersion = 0x300;
- plogPal->palNumEntries = (uint16_t) iEntries;
- pjTmp = (PBYTE) plogPal;
- pjTmp += 4;
-
- GetEnhMetaFilePaletteEntries(hMeta, iEntries, (PPALETTEENTRY)pjTmp);
- hPal = CreatePalette(plogPal);
- GlobalFree(plogPal);
-
- SelectPalette(hDC, hPal, FALSE);
- RealizePalette(hDC);
- }
-
- // Play the Metafile into Memory DC
- BOOL bRet = PlayEnhMetaFile(hDC, // handle to a device context
- hMeta, // handle to an enhanced metafile
- &rc); // pointer to bounding rectangle
-
- SelectObject(hDC, hBitmapOld);
- DeleteEnhMetaFile(hMeta); // we are done with this one
-
- if (info.nEscape) { // Check if cancelled
- DeleteObject(hBitmap);
- DeleteDC(hDC);
- strcpy(info.szLastError,"Cancelled");
- return false;
- }
-
- // the Bitmap now has the image.
- // Create our DIB and convert the DDB into DIB
- if (!Create(cx, cy, bpp, CXIMAGE_FORMAT_WMF)) {
- DeleteObject(hBitmap);
- DeleteDC(hDC);
- return false;
- }
-
-#if XMF_SUPPORT_TRANSPARENCY
- if (bpp == 24) {
- RGBQUAD rgbTrans = { XMF_RGBQUAD_TRANSPARENT };
- SetTransColor(rgbTrans);
- }
-#endif
- // We're finally ready to get the DIB. Call the driver and let
- // it party on our bitmap. It will fill in the color table,
- // and bitmap bits of our global memory block.
- bRet = GetDIBits(hDC, hBitmap, 0,
- (uint32_t)cy, GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);
-
- DeleteObject(hBitmap);
- DeleteDC(hDC);
-
- return (bRet!=0);
- } else {
- DeleteDC(hDC);
- }
- } else {
- if (hBitmap) DeleteObject(hBitmap);
- }
-
- DeleteEnhMetaFile(hMeta);
-
- return false;
-}
-
-/**********************************************************************
- Function: CheckMetafileHeader
- Purpose: Check if the Metafileheader of a file is valid
-**********************************************************************/
-BOOL CxImageWMF::CheckMetafileHeader(METAFILEHEADER *metafileheader)
-{
- uint16_t *pw;
- uint16_t cs;
- int32_t i;
-
- // check magic #
- if (metafileheader->key != 0x9ac6cdd7L) return false;
-
- // test checksum of header
- pw = (uint16_t *)metafileheader;
- cs = *pw;
- pw++;
- for (i = 0; i < 9; i++) {
- cs ^= *pw;
- pw++;
- }
-
- if (cs != metafileheader->checksum) return false;
-
- // check resolution
- if ((metafileheader->inch <= 0) || (metafileheader->inch > 2540)) return false;
-
- return true;
-}
-
-/**********************************************************************
- Function: ConvertWmfFiletoEmf
- Purpose: Converts a Windows Metafile into an Enhanced Metafile
-**********************************************************************/
-HENHMETAFILE CxImageWMF::ConvertWmfFiletoEmf(CxFile *fp, METAFILEHEADER *metafileheader)
-{
- HENHMETAFILE hMeta;
- uint32_t lenFile;
- uint32_t len;
- uint8_t *p;
- METAHEADER mfHeader;
- uint32_t seekpos;
-
- hMeta = 0;
-
- // get length of the file
- lenFile = fp->Size();
-
- // a placeable metafile starts with a METAFILEHEADER
- // read it and check metafileheader
- len = fp->Read(metafileheader, 1, sizeof(METAFILEHEADER));
- if (len < sizeof(METAFILEHEADER)) return (hMeta);
-
- if (CheckMetafileHeader(metafileheader)) {
- // This is a placeable metafile
- // Convert the placeable format into something that can
- // be used with GDI metafile functions
- seekpos = sizeof(METAFILEHEADER);
- } else {
- // Not a placeable wmf. A windows metafile?
- // at least not scaleable.
- // we could try to convert, but would loose ratio. don't allow this
- return (hMeta);
-
- //metafileheader->bbox.right = ?;
- //metafileheader->bbox.left = ?;
- //metafileheader->bbox.bottom = ?;
- //metafileheader->bbox.top = ?;
- //metafileheader->inch = ?;
- //
- //seekpos = 0;
- // fp->Seek(0, SEEK_SET); // rewind
- }
-
- // At this point we have a metaheader regardless of whether
- // the metafile was a windows metafile or a placeable metafile
- // so check to see if it is valid. There is really no good
- // way to do this so just make sure that the mtType is either
- // 1 or 2 (memory or disk file)
- // in addition we compare the length of the METAHEADER against
- // the length of the file. if filelength < len => no Metafile
-
- len = fp->Read(&mfHeader, 1, sizeof(METAHEADER));
- if (len < sizeof(METAHEADER)) return (hMeta);
-
- if ((mfHeader.mtType != 1) && (mfHeader.mtType != 2)) return (hMeta);
-
- // Length in Bytes from METAHEADER
- len = mfHeader.mtSize * 2;
- if (len > lenFile) return (hMeta);
-
- // Allocate memory for the metafile bits
- p = (uint8_t *)malloc(len);
- if (!p) return (hMeta);
-
- // seek back to METAHEADER and read all the stuff at once
- fp->Seek(seekpos, SEEK_SET);
- lenFile = fp->Read(p, 1, len);
- if (lenFile != len) {
- free(p);
- return (hMeta);
- }
-
- // the following (commented code) works, but adjusts rclBound of the
- // Enhanced Metafile to full screen.
- // the METAFILEHEADER from above is needed to scale the image
-
-// hMeta = SetWinMetaFileBits(len, p, NULL, NULL);
-
- // scale the metafile (pixels/inch of metafile => pixels/inch of display)
-
- METAFILEPICT mfp;
- int32_t cx1, cy1;
- HDC hDC;
-
- hDC = ::GetDC(0);
- cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);
- cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);
-
- memset(&mfp, 0, sizeof(mfp));
-
- mfp.mm = MM_ANISOTROPIC;
- mfp.xExt = 10000; //(metafileheader->bbox.right - metafileheader->bbox.left) * cx1 / metafileheader->inch;
- mfp.yExt = 10000; //(metafileheader->bbox.bottom - metafileheader->bbox.top) * cy1 / metafileheader->inch;
- mfp.hMF = 0;
-
- // in MM_ANISOTROPIC mode xExt and yExt are in MM_HIENGLISH
- // MM_HIENGLISH means: Each logical unit is converted to 0.001 inch
- //mfp.xExt *= 1000;
- //mfp.yExt *= 1000;
- // ????
- //int32_t k = 332800 / ::GetSystemMetrics(SM_CXSCREEN);
- //mfp.xExt *= k; mfp.yExt *= k;
-
- // fix for Win9x
- while ((mfp.xExt < 6554) && (mfp.yExt < 6554))
- {
- mfp.xExt *= 10;
- mfp.yExt *= 10;
- }
-
- hMeta = SetWinMetaFileBits(len, p, hDC, &mfp);
-
- if (!hMeta){ //try 2nd conversion using a different mapping
- mfp.mm = MM_TEXT;
- hMeta = SetWinMetaFileBits(len, p, hDC, &mfp);
- }
-
- ::ReleaseDC(0, hDC);
-
- // Free Memory
- free(p);
-
- return (hMeta);
-}
-/////////////////////////////////////////////////////////////////////
-HENHMETAFILE CxImageWMF::ConvertEmfFiletoEmf(CxFile *pFile, ENHMETAHEADER *pemfh)
-{
- HENHMETAFILE hMeta;
- int32_t iLen = pFile->Size();
-
- // Check the header first: <km>
- int32_t pos = pFile->Tell();
- int32_t iLenRead = pFile->Read(pemfh, 1, sizeof(ENHMETAHEADER));
- if (iLenRead < sizeof(ENHMETAHEADER)) return NULL;
- if (pemfh->iType != EMR_HEADER) return NULL;
- if (pemfh->dSignature != ENHMETA_SIGNATURE) return NULL;
- //if (pemfh->nBytes != (uint32_t)iLen) return NULL;
- pFile->Seek(pos,SEEK_SET);
-
- uint8_t* pBuff = (uint8_t *)malloc(iLen);
- if (!pBuff) return (FALSE);
-
- // Read the Enhanced Metafile
- iLenRead = pFile->Read(pBuff, 1, iLen);
- if (iLenRead != iLen) {
- free(pBuff);
- return NULL;
- }
-
- // Make it a Memory Metafile
- hMeta = SetEnhMetaFileBits(iLen, pBuff);
-
- free(pBuff); // finished with this one
-
- if (!hMeta) return NULL; // oops.
-
- // Get the Enhanced Metafile Header
- uint32_t uRet = GetEnhMetaFileHeader(hMeta, // handle of enhanced metafile
- sizeof(ENHMETAHEADER), // size of buffer, in bytes
- pemfh); // address of buffer to receive data
-
- if (!uRet) {
- DeleteEnhMetaFile(hMeta);
- return NULL;
- }
-
- return (hMeta);
-}
-////////////////////////////////////////////////////////////////////////////////
-#endif //CXIMAGE_SUPPORT_DECODE
-////////////////////////////////////////////////////////////////////////////////
-#if CXIMAGE_SUPPORT_ENCODE
-/////////////////////////////////////////////////////////////////////
-bool CxImageWMF::Encode(CxFile * hFile)
-{
- if (hFile == NULL) return false;
- strcpy(info.szLastError, "Save WMF not supported");
- return false;
-}
-#endif // CXIMAGE_SUPPORT_ENCODE
-/////////////////////////////////////////////////////////////////////
-
-/**********************************************************************
-Function: ShrinkMetafile
-Purpose: Shrink the size of a metafile to be not larger than
- the definition
-**********************************************************************/
-void CxImageWMF::ShrinkMetafile(int32_t &cx, int32_t &cy)
-{
- int32_t xScreen = XMF_MAXSIZE_CX;
- int32_t yScreen = XMF_MAXSIZE_CY;
-
- if (cx > xScreen){
- cy = cy * xScreen / cx;
- cx = xScreen;
- }
-
- if (cy > yScreen){
- cx = cx * yScreen / cy;
- cy = yScreen;
- }
-}
-
-#endif // CIMAGE_SUPPORT_WMF
-