home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / METAFILE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  9.3 KB  |  384 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.8  $
  6. //
  7. // Implementation of TMetaFilePict class
  8. //----------------------------------------------------------------------------
  9. #pragma hdrignore SECTION
  10. #include <owl/pch.h>
  11. #if !defined(OWL_METAFILE_H)
  12. # include <owl/metafile.h>
  13. #endif
  14. #if !defined(OWL_GDIOBJEC_H)
  15. # include <owl/gdiobjec.h>
  16. #endif
  17. #if !defined(OWL_CLIPBOAR_H)
  18. # include <owl/clipboar.h>
  19. #endif
  20. #if !defined(OWL_EXCEPT_H)
  21. # include <owl/except.h>
  22. #endif
  23. #if !defined(CLASSLIB_FILE_H)
  24. # include <classlib/file.h>
  25. #endif
  26.  
  27. OWL_DIAGINFO;
  28. DIAG_DECLARE_GROUP(OwlGDI);        // General GDI diagnostic group
  29.  
  30. // Constant for checking validity of a METAFILEHEADER
  31. //
  32. const uint32 TMetaFilePict::MFHeaderKey = 0x9AC6CDD7L;
  33.  
  34. //
  35. // Alias an existing meta file handle.
  36. //
  37. TMetaFilePict::TMetaFilePict(HMETAFILE handle, TAutoDelete autoDelete)
  38. :
  39.   TGdiBase(handle, autoDelete),
  40.   Extent(0,0),
  41.   Placeable(false)
  42. {
  43.   Mm = MM_ANISOTROPIC;
  44. }
  45.  
  46. //
  47. // Create a metafile object from an external file.
  48. //
  49. TMetaFilePict::TMetaFilePict(const char* filename)
  50. :
  51.   Extent(0,0),
  52.   Placeable(false)
  53. {
  54.   TFile file;
  55.  
  56.   file.Open(filename, O_RDONLY, SH_DENYWR);
  57.   file.Read(&MFHeader, sizeof(MFHeader));
  58.  
  59.   // Determine whether this file begins with a valid METAFILEHEADER
  60.   // struct and load the file accordingly.
  61.   //
  62.   if ((MFHeader.key == MFHeaderKey)
  63.       && (MFHeader.checksum == CalcHeaderChecksum(MFHeader)))
  64.   {
  65.     // Determine size of metafile data
  66.     //
  67.     TFileStatus status;
  68.     file.GetStatus(status);
  69.     long size = status.size - sizeof(METAFILEHEADER);
  70.  
  71.     // Convert the data to a metafile
  72.     //
  73.     HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, size);
  74.     if (!hMem)
  75.       TXOutOfMemory::Raise();
  76.     unsigned char _huge* pMem = (unsigned char _huge*)GlobalLock(hMem);
  77.     file.Read((void _huge*)pMem, size);
  78.  
  79. #if defined(BI_PLAT_WIN32)
  80.     Handle = SetMetaFileBitsEx(size, pMem);
  81.     GlobalUnlock(hMem);
  82. #else
  83.     Handle = SetMetaFileBits(hMem);
  84.     GlobalUnlock(hMem);    
  85. #endif
  86.  
  87.     // Remember that this metafile comes with a placeable header
  88.     // (in other words, MFHeader holds valid data)
  89.     //
  90.     if (Handle)
  91.       Placeable = true;
  92.  
  93.     // Placeable metafiles are meant to be played back in
  94.     // the unconstrained mapping mode.  The header tells
  95.     // the desired size and aspect ratio.
  96.     //
  97.     Mm = MM_ANISOTROPIC;
  98.  
  99.     // Set metafile dimensions according to info in header
  100.     //
  101.     Extent.cx = MFHeader.bbox.right - MFHeader.bbox.left;
  102.     Extent.cy = MFHeader.bbox.bottom - MFHeader.bbox.top;
  103.  
  104.     // Convert dimensions to HIMETRIC units (.001 cm)
  105.     //
  106.     Extent.cx = MulDiv(Extent.cx, 2540, MFHeader.inch);
  107.     Extent.cy = MulDiv(Extent.cy, 2540, MFHeader.inch);
  108.   }  
  109.   else {
  110.     Mm = MM_ANISOTROPIC;
  111.     Handle = ::GetMetaFile(filename);
  112.   }
  113.   ShouldDelete = true;
  114.   file.Close();
  115.   CheckValid();
  116. }
  117.  
  118. //
  119. // Construct a TMetaFilePict that represents the metafilepict on the clipboard.
  120. // Should be copied if metafile needs to be kept.
  121. //
  122. TMetaFilePict::TMetaFilePict(const TClipboard&)
  123. :
  124.   Extent(0,0),
  125.   Placeable(false)
  126. {
  127.   HGLOBAL hmfp = ::GetClipboardData(CF_METAFILEPICT);
  128.   METAFILEPICT far* mfp = (METAFILEPICT far*)::GlobalLock(hmfp);
  129.  
  130.   if (mfp) {
  131.     Mm = mfp->mm;
  132.     Extent = TSize(mfp->xExt, mfp->yExt);
  133.     Handle = mfp->hMF;
  134.     ::GlobalUnlock(hmfp);
  135.   }
  136.   else
  137.     Handle = 0;
  138.  
  139.   ShouldDelete = false;
  140.   CheckValid();
  141. }
  142.  
  143. #if defined(BI_PLAT_WIN32)
  144.  
  145. //
  146. // Create an enhanced metafile from a memory buffer.
  147. //
  148. TMetaFilePict::TMetaFilePict(uint size, void* data)
  149. :
  150.   TGdiBase(::SetMetaFileBitsEx(size, (LPBYTE)data), NoAutoDelete),
  151.   Extent(0,0),
  152.   Placeable(false)
  153. {
  154.   CheckValid();
  155.   Mm = MM_ANISOTROPIC;
  156. }
  157.  
  158. #else
  159.  
  160. //
  161. // Create a meta file from a memory buffer.
  162. //
  163. TMetaFilePict::TMetaFilePict(HGLOBAL data)
  164. :
  165.   TGdiBase(::SetMetaFileBitsBetter(data), NoAutoDelete),
  166.   Extent(0,0),
  167.   Placeable(false)
  168. {
  169.   CheckValid();
  170.   Mm = MM_ANISOTROPIC;
  171. }
  172.  
  173. #endif
  174.  
  175. //
  176. // Copy the metafile.
  177. //
  178. TMetaFilePict::TMetaFilePict(const TMetaFilePict& src, const char far* fileName)
  179. :
  180.   TGdiBase(::CopyMetaFile(src, fileName), AutoDelete),
  181.   Extent(src.Extent),
  182.   Placeable(false)
  183. {
  184.   CheckValid();
  185.   Mm = src.Mm;
  186. }
  187.  
  188. //
  189. // Delete the metafile.
  190. //
  191. TMetaFilePict::~TMetaFilePict()
  192. {
  193.   if (ShouldDelete && Handle)
  194.     ::DeleteMetaFile(HMETAFILE(Handle));
  195. }
  196.  
  197. //
  198. // Read the fields in the file header structure of a placeable
  199. // metafile and compute a checksum value for verifying the
  200. // header's integrity.
  201. //
  202. uint16
  203. TMetaFilePict::CalcHeaderChecksum(const METAFILEHEADER& header)
  204. {
  205.   LPWORD lpw;             // pointer to words in header 
  206.   uint16 checksum = 0;
  207.  
  208.   for (lpw = (LPWORD)&header;
  209.        lpw < (LPWORD)&header.checksum;
  210.        ++lpw)
  211.   {
  212.     // XOR current checksum with next field 
  213.     //
  214.     checksum ^= *lpw;
  215.   }
  216.  
  217.   return checksum;
  218. }
  219.  
  220. #if defined(BI_PLAT_WIN32)
  221.  
  222. //
  223. // Retrieve the bits of the metafile.
  224. //
  225. uint32
  226. TMetaFilePict::GetMetaFileBitsEx(uint size, void* data)
  227. {
  228.   return ::GetMetaFileBitsEx(HMETAFILE(Handle), size, (LPBYTE)data);
  229. }
  230.  
  231. #endif
  232.  
  233. //
  234. // Calculates target play size based on info from the metafilepict (if any)
  235. // and default target size as necessary
  236. //
  237. TSize
  238. TMetaFilePict::CalcPlaySize(TDC& dc, const TSize& defSize) const
  239. {
  240.   // Given a fixed mapping mode, return precalculated extents
  241.   //
  242.   if (Mm != MM_ISOTROPIC && Mm != MM_ANISOTROPIC) {
  243.     WARNX(OwlGDI, (Extent.X() == 0) || (Extent.Y() == 0), 0, "Constrained metafile extent == 0");
  244.     return Extent;    // Assumes extents were calculated correctly.
  245.   }
  246.  
  247.   //
  248.   // Metafile uses partially constrained or unconstrained mapping mode
  249.   //
  250.  
  251.   // If no extent info given, then use defaults
  252.   //
  253.   if (Extent.X() == 0) {
  254.     WARNX(OwlGDI, (defSize.X() == 0) || (defSize.Y() == 0), 0, "Metafile using default extent == 0");
  255.     return defSize;
  256.   }
  257.  
  258.   // Use positive extents scaled to 0.01mm units
  259.   //
  260.   else if (Extent.cx > 0) {
  261.     return TSize(
  262.         int(long(Extent.cx)*dc.GetDeviceCaps(HORZRES)/dc.GetDeviceCaps(HORZSIZE)/100),
  263.         int(long(Extent.cy)*dc.GetDeviceCaps(VERTRES)/dc.GetDeviceCaps(VERTSIZE)/100)
  264.       );
  265.   }
  266.   // Use negative extents scaled to 0.01mm units w/ aspect ratio scaling
  267.   //
  268.   else {
  269.     long xscale = 100L * defSize.cx *
  270.       dc.GetDeviceCaps(HORZSIZE)/dc.GetDeviceCaps(HORZRES) / -Extent.cx;
  271.     long yscale = 100L * defSize.cy *
  272.       dc.GetDeviceCaps(VERTSIZE)/dc.GetDeviceCaps(VERTRES) / -Extent.cy;
  273.     long scale = min(xscale, yscale);
  274.     return TSize(
  275.       int(long(-Extent.cx)*scale*dc.GetDeviceCaps(HORZRES)/dc.GetDeviceCaps(HORZSIZE) / 100),
  276.       int(long(-Extent.cy)*scale*dc.GetDeviceCaps(VERTRES)/dc.GetDeviceCaps(VERTSIZE) / 100)
  277.     );
  278.   }
  279. }
  280.  
  281. //
  282. // Play this metafile onto a dc, possibly using a default size if this
  283. // metafile doesn't have one. Does not save dc state.
  284. //
  285. bool
  286. TMetaFilePict::PlayOnto(TDC& dc, const TSize& defSize) const
  287. {
  288.   // Set target dc's mapping mode to this metafile's if there is one
  289.   //
  290.   if (Mm)
  291.     dc.SetMapMode(Mm);
  292.  
  293.   // Set the viewport extent to the area that the metafile will fill
  294.   //
  295.   if (Mm == MM_ISOTROPIC || Mm == MM_ANISOTROPIC)
  296.     dc.SetViewportExt(CalcPlaySize(dc, defSize));
  297.  
  298.   return ::PlayMetaFile(dc, *this);
  299. }
  300.  
  301. //
  302. // Move this metafile to the clipboard inside of a metafilepict struct.
  303. // Ownership of the metafilepict as well as the metafile is passed to the
  304. // clipboard.
  305. //
  306. void
  307. TMetaFilePict::ToClipboard(TClipboard& clipboard, unsigned mapMode,
  308.                            const TSize& extent)
  309. {
  310.  
  311.   HGLOBAL hmfp = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
  312.   if (!hmfp)
  313.     TXOutOfMemory::Raise();
  314.   METAFILEPICT far* mfp = (METAFILEPICT far*)::GlobalLock(hmfp);
  315.   mfp->mm = mapMode;
  316.   mfp->xExt = extent.cx;
  317.   mfp->yExt = extent.cy;
  318.   mfp->hMF = (HMETAFILE)Handle;
  319.   ::GlobalUnlock(hmfp);
  320.  
  321.   clipboard.SetClipboardData(CF_METAFILEPICT, hmfp);
  322.   ShouldDelete = false;
  323. }
  324.  
  325. #if defined(BI_PLAT_WIN32)
  326.  
  327. //
  328. // Alias an existing enhanced metafile handle.
  329. //
  330. TEnhMetaFilePict::TEnhMetaFilePict(HENHMETAFILE handle, TAutoDelete autoDelete)
  331. :
  332.   TGdiBase(handle, autoDelete)
  333. {
  334. }
  335.  
  336. //
  337. // Create an enhanced metafile from an external file.
  338. //
  339. TEnhMetaFilePict::TEnhMetaFilePict(const char* filename)
  340. :
  341.   TGdiBase(::GetEnhMetaFile(filename), AutoDelete)
  342. {
  343. }
  344.  
  345. //
  346. // Copy a metafile
  347. //
  348. TEnhMetaFilePict::TEnhMetaFilePict(const TEnhMetaFilePict& metafilepict,
  349.                                    const char far* filename)
  350. :
  351.   TGdiBase(::CopyEnhMetaFile(metafilepict, filename), AutoDelete)
  352. {
  353. }
  354.  
  355. //
  356. // Create metafile from buffer
  357. //
  358. TEnhMetaFilePict::TEnhMetaFilePict(uint bytes, const void* buffer)
  359. :
  360.   TGdiBase(::SetEnhMetaFileBits(bytes, (const BYTE*)buffer), AutoDelete)
  361. {
  362. }
  363.  
  364. //
  365. // Destroy the enhanced metafile picture.
  366. //
  367. TEnhMetaFilePict::~TEnhMetaFilePict()
  368. {
  369.   if (ShouldDelete && Handle)
  370.     ::DeleteEnhMetaFile(HENHMETAFILE(Handle));
  371. }
  372.  
  373. //
  374. // Plays the metafile onto a device context.
  375. //
  376. bool
  377. TEnhMetaFilePict::PlayOnto(TDC& dc, const TRect* rect) const
  378. {
  379.   return ::PlayEnhMetaFile(dc, *this, rect);
  380. }
  381.  
  382.  
  383. #endif  // BI_PLAT_WIN32
  384.