home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / ODF Release 3 / ODFDev / ODF / OS / FWGraphx / PRBitmap.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  39.4 KB  |  1,473 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                PRBitmap.cpp
  4. //    Release Version:    $ ODF 3 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef SLPALETE_H
  13. #include "SLPalete.h"
  14. #endif
  15.  
  16. #ifndef FWODEXCE_H
  17. #include "FWODExce.h"
  18. #endif
  19.  
  20. #ifndef FWBITMAP_H
  21. #include "FWBitmap.h"
  22. #endif
  23.  
  24. #ifndef PRBITMAP_H
  25. #include "PRBitmap.h"
  26. #endif
  27.  
  28. #ifndef SLGC_H
  29. #include "SLGC.h"
  30. #endif
  31.  
  32. #ifndef FWWINRES_H
  33. #include "FWWinRes.h"
  34. #endif
  35.  
  36. #ifndef FWSTRMRW_H
  37. #include "FWStrmRW.h"
  38. #endif
  39.  
  40. #ifndef FWRESOUR_H
  41. #include "FWResour.h"
  42. #endif
  43.  
  44. #ifndef FWGRUTIL_H
  45. #include "FWGrUtil.h"
  46. #endif
  47.  
  48. #ifndef FWPALETE_H
  49. #include "FWPalete.h"
  50. #endif
  51.  
  52. #ifndef FWSOMENV_H
  53. #include "FWSOMEnv.h"
  54. #endif
  55.  
  56. #ifndef PRGRUTIL_H
  57. #include "PRGrUtil.h"
  58. #endif
  59.  
  60. #ifndef   FWMEMHLP_H
  61. #include "FWMemHlp.h"
  62. #endif
  63.  
  64. #ifndef FWEXCEPT_H
  65. #include "FWExcept.h"
  66. #endif
  67.  
  68. #if defined(FW_BUILD_WIN) && !defined(FWWINDIB_H)
  69. #include "FWWinDIB.h"
  70. #endif
  71.  
  72. #if defined(FW_BUILD_MAC) && !defined(__PICTUTILS__)
  73. #include <PictUtils.h>
  74. #endif
  75.  
  76. #ifndef PRPICTUR_H
  77. #include "PRPictur.h"
  78. #endif
  79.  
  80. //========================================================================================
  81. //    RunTime Info
  82. //========================================================================================
  83.  
  84. #ifdef FW_BUILD_MAC
  85. #pragma segment FW_Graphics
  86. #endif
  87.  
  88. FW_DEFINE_AUTO(FW_CPrivBitmapRep)
  89.  
  90. //========================================================================================
  91. // CLASS FW_CPrivBitmapRep
  92. //========================================================================================
  93.  
  94. #ifdef FW_BUILD_MAC
  95.  
  96. //========================================================================================
  97. //    class FW_PrivSetRestoreGWorld
  98. //========================================================================================
  99.  
  100. class FW_PrivSetRestoreGWorld
  101. {
  102. public:
  103.     FW_DECLARE_AUTO(FW_PrivSetRestoreGWorld)
  104.  
  105.     FW_PrivSetRestoreGWorld(CGrafPtr tempPort = NULL, GDHandle tempDevice = NULL);
  106.     FW_PrivSetRestoreGWorld(GrafPtr tempPort, GDHandle tempDevice = NULL);
  107.     
  108.     ~FW_PrivSetRestoreGWorld();
  109.  
  110. private:
  111.     
  112.     CGrafPtr    fMacPort;
  113.     GDHandle    fGDevice;
  114. };
  115.  
  116. FW_DEFINE_AUTO(FW_PrivSetRestoreGWorld)
  117.  
  118. //----------------------------------------------------------------------------------------
  119. //    FW_PrivSetRestoreGWorld::FW_PrivSetRestoreGWorld
  120. //----------------------------------------------------------------------------------------
  121.  
  122. inline FW_PrivSetRestoreGWorld::FW_PrivSetRestoreGWorld(CGrafPtr tempPort /* = NULL */, GDHandle tempDevice /* = NULL */)
  123. {
  124.     ::GetGWorld(&fMacPort, &fGDevice);
  125.  
  126.     if (tempPort != NULL)
  127.         SetGWorld(tempPort, tempDevice);
  128.         
  129.     FW_END_CONSTRUCTOR
  130. }
  131.  
  132. //----------------------------------------------------------------------------------------
  133. //    FW_PrivSetRestoreGWorld::FW_PrivSetRestoreGWorld
  134. //----------------------------------------------------------------------------------------
  135.  
  136. inline FW_PrivSetRestoreGWorld::FW_PrivSetRestoreGWorld(GrafPtr tempPort, GDHandle tempDevice /* = NULL */)
  137. {
  138.     ::GetGWorld(&fMacPort, &fGDevice);
  139.  
  140.     if (tempPort != NULL)
  141.         SetGWorld((CGrafPtr) tempPort, tempDevice);
  142.         
  143.     FW_END_CONSTRUCTOR
  144. }
  145.  
  146. //----------------------------------------------------------------------------------------
  147. //    FW_PrivSetRestoreGWorld::~FW_PrivSetRestoreGWorld
  148. //----------------------------------------------------------------------------------------
  149.  
  150. inline FW_PrivSetRestoreGWorld::~FW_PrivSetRestoreGWorld()
  151. {
  152.     FW_START_DESTRUCTOR
  153.     
  154.     ::SetGWorld(fMacPort, fGDevice);
  155. }
  156.  
  157. //----------------------------------------------------------------------------------------
  158. //    class FW_CSetHeapZone
  159. //----------------------------------------------------------------------------------------
  160.  
  161. class FW_CSetHeapZone
  162. {
  163. public:
  164.     FW_DECLARE_AUTO(FW_CSetHeapZone)
  165.     
  166.     FW_CSetHeapZone(THz inZone);
  167.     ~FW_CSetHeapZone();
  168.  
  169. private:
  170.     THz fSaveZone;
  171. };
  172.  
  173. FW_DEFINE_AUTO(FW_CSetHeapZone)
  174.  
  175. inline FW_CSetHeapZone::FW_CSetHeapZone(THz inZone)
  176. :    fSaveZone(::GetZone())
  177. {
  178.     ::SetZone(inZone);
  179.     
  180.     FW_END_CONSTRUCTOR
  181. }
  182.  
  183. inline FW_CSetHeapZone::~FW_CSetHeapZone()
  184. {
  185.     FW_START_DESTRUCTOR
  186.     
  187.     ::SetZone(fSaveZone);
  188. }
  189.  
  190. #endif
  191.  
  192. #ifdef FW_BUILD_MAC
  193.  
  194. // Special Russian value swapping: uses no temporary
  195.  
  196. #define SWAP(a, b)     do { (a) = (a) ^ (b);    (b) = (a) ^ (b); (a) = (a) ^ (b); } while(0)
  197.  
  198. //----------------------------------------------------------------------------------------
  199. //    MacRepackResourceRow
  200. //----------------------------------------------------------------------------------------
  201.  
  202. static void MacRepackResourceRow(char* curBuffer, short bitDepth, short resRowBytes)
  203. {
  204.     short pixelBytes = bitDepth / 8;
  205.  
  206.     if(pixelBytes == 2)
  207.     {
  208.         do
  209.         {
  210.             SWAP(curBuffer[0], curBuffer[1]);
  211.         }
  212.         while((resRowBytes -= pixelBytes) > 0);
  213.     }
  214.     else if(pixelBytes == 4)
  215.     {
  216.         do
  217.         {
  218.             SWAP(curBuffer[0], curBuffer[3]);
  219.             SWAP(curBuffer[1], curBuffer[2]);
  220.         }
  221.         while((resRowBytes -= pixelBytes) > 0);
  222.     }
  223. }
  224.  
  225. //----------------------------------------------------------------------------------------
  226. //    MacRepackValue
  227. //----------------------------------------------------------------------------------------
  228.  
  229. static void MacRepackValue(short* s)
  230. {
  231.     char* c = (char*) s;
  232.     SWAP(c[0], c[1]);
  233. }
  234.  
  235. static void MacRepackValue(unsigned short* s)
  236. {
  237.     char* c = (char*) s;
  238.     SWAP(c[0], c[1]);
  239. }
  240.  
  241. static void MacRepackValue(long* l)
  242. {
  243.     char* c = (char*) l;
  244.     SWAP(c[0], c[3]);
  245.     SWAP(c[1], c[2]);
  246. }
  247.  
  248. static void MacRepackValue(unsigned long* l)
  249. {
  250.     char* c = (char*) l;
  251.     SWAP(c[0], c[3]);
  252.     SWAP(c[1], c[2]);
  253. }
  254.  
  255. #endif
  256.  
  257. //----------------------------------------------------------------------------------------
  258. //    FW_CPrivBitmapRep::FW_CPrivBitmapRep
  259. //----------------------------------------------------------------------------------------
  260. // From image: will own the bitmap
  261.  
  262. FW_CPrivBitmapRep::FW_CPrivBitmapRep(short width,  short height,
  263.                                     short pixelSize, FW_Palette palette,
  264.                                     void* image, long imageSize, short rowBytes) :
  265.     fOwnBitmap(TRUE),
  266.     fPlatformBitmap(NULL)
  267. {
  268. #ifdef FW_BUILD_MAC
  269.     fLockCount = 0;
  270.     fPixMapHandle = NULL;
  271. #endif
  272. #ifdef FW_BUILD_WIN
  273.     fUserColorDepth = 0;
  274.     fWinPalette = NULL;
  275. #endif
  276.  
  277.     PrivMakeBitmap(width, height, pixelSize, palette);
  278.         
  279.     if (image != NULL)
  280.         SetImage(image, imageSize, rowBytes);
  281.         
  282.     FW_END_CONSTRUCTOR
  283. }
  284.  
  285. //----------------------------------------------------------------------------------------
  286. //    FW_CPrivBitmapRep::FW_CPrivBitmapRep
  287. //----------------------------------------------------------------------------------------
  288. // From platform bitmap: will not own the bitmap
  289.  
  290. FW_CPrivBitmapRep::FW_CPrivBitmapRep(FW_PlatformBitmap platformBitmap) :
  291.     fOwnBitmap(FALSE),
  292.     fPlatformBitmap(platformBitmap)
  293. {
  294. #ifdef FW_BUILD_MAC
  295.     fLockCount = 0;
  296.     fPixMapHandle = NULL;
  297. #endif
  298. #ifdef FW_BUILD_WIN
  299.     fUserColorDepth = FW_DDBGetColorDepth(fPlatformBitmap);
  300.     fWinPalette = NULL;
  301. #endif
  302.  
  303.     FW_END_CONSTRUCTOR
  304. }
  305.  
  306. //----------------------------------------------------------------------------------------
  307. //    FW_CPrivBitmapRep::FW_CPrivBitmapRep
  308. //----------------------------------------------------------------------------------------
  309. // From resources: will own the bitmap
  310.  
  311. FW_CPrivBitmapRep::FW_CPrivBitmapRep(FW_OResourceFile* resourceFile, FW_ResourceID resID) :
  312.     fOwnBitmap(TRUE),
  313.     fPlatformBitmap(NULL)
  314. {
  315. #ifdef FW_BUILD_MAC
  316.     fLockCount = 0;
  317.     fPixMapHandle = NULL;
  318. #endif
  319. #ifdef FW_BUILD_WIN
  320.     fUserColorDepth = 0;
  321.     fWinPalette = NULL;
  322. #endif
  323.  
  324.     fPlatformBitmap = NULL;
  325.  
  326.     FW_SOMEnvironment ev;
  327.     FW_PResource resource(ev, resourceFile, resID, FW_kBitmap);
  328.     FW_PResourceSink sink(ev, resource);
  329.     FW_CReadableStream stream(sink);
  330.  
  331. #ifdef FW_BUILD_WIN
  332.     PrivReadFromStream(stream, FALSE);
  333. #endif
  334. #ifdef FW_BUILD_MAC
  335.     PrivReadFromStream(stream, TRUE);
  336. #endif
  337.     
  338.     FW_END_CONSTRUCTOR
  339. }
  340.  
  341. //----------------------------------------------------------------------------------------
  342. //    FW_CPrivBitmapRep::FW_CPrivBitmapRep
  343. //----------------------------------------------------------------------------------------
  344. // From another bitmap: will own the bitmap (a copy is made)
  345.  
  346. FW_CPrivBitmapRep::FW_CPrivBitmapRep(const FW_CPrivBitmapRep& bitmap, const FW_SRect& srcRect) :
  347.     fOwnBitmap(TRUE),
  348.     fPlatformBitmap(NULL)    
  349. {
  350. #ifdef FW_BUILD_MAC
  351.     fLockCount = 0;
  352.     fPixMapHandle = NULL;
  353. #endif
  354. #ifdef FW_BUILD_WIN
  355.     fUserColorDepth = 0;
  356.     fWinPalette = NULL;
  357. #endif
  358.  
  359.     FW_CRect bounds;
  360.     bitmap.GetBitmapBounds(bounds);
  361.     
  362.     FW_CRect clipRect = srcRect;
  363.  
  364.     if (clipRect.left < FW_kFixed0) 
  365.         clipRect.left = FW_kFixed0;
  366.     else if (clipRect.left > bounds.right) 
  367.         clipRect.left = bounds.right;
  368.         
  369.     if (clipRect.top < FW_kFixed0) 
  370.         clipRect.top = FW_kFixed0;
  371.     else if (clipRect.top > bounds.bottom) 
  372.         clipRect.top = bounds.bottom;
  373.     
  374.     if (clipRect.right > bounds.right) 
  375.         clipRect.right = bounds.right;
  376.     else if (clipRect.right < clipRect.left)
  377.         clipRect.right = clipRect.left;
  378.     
  379.     if (clipRect.bottom > bounds.bottom) 
  380.         clipRect.bottom = bounds.bottom;
  381.     else if (clipRect.bottom < clipRect.top) 
  382.         clipRect.bottom = clipRect.top;
  383.  
  384.     FW_CRect dstRect(FW_kFixed0, FW_kFixed0, clipRect.right - clipRect.left, clipRect.bottom - clipRect.top);
  385.  
  386.     short width, height, rowBytes, pixelSize;
  387.     bitmap.GetBitmapInfo(width, height, rowBytes, pixelSize);
  388.     
  389.     FW_Palette palette = bitmap.GetPalette();
  390.     PrivMakeBitmap(
  391.         FW_FixedToInt(clipRect.right - clipRect.left),
  392.         FW_FixedToInt(clipRect.bottom - clipRect.top), pixelSize, palette);
  393.  
  394.     bitmap.CopyPixels(*this, clipRect, dstRect);
  395.     
  396.     FW_END_CONSTRUCTOR
  397. }
  398.  
  399. //----------------------------------------------------------------------------------------
  400. //    FW_CPrivBitmapRep::~FW_CPrivBitmapRep
  401. //----------------------------------------------------------------------------------------
  402.  
  403. FW_CPrivBitmapRep::~FW_CPrivBitmapRep()
  404. {
  405.     PrivDisposeBitmap();
  406. }
  407.  
  408. //----------------------------------------------------------------------------------------
  409. //    FW_CPrivBitmapRep::IsEqual
  410. //----------------------------------------------------------------------------------------
  411.  
  412. FW_Boolean FW_CPrivBitmapRep::IsEqual(const FW_CPrivBitmapRep& bitmap) const
  413. {
  414.     return fPlatformBitmap == bitmap.fPlatformBitmap;
  415. }
  416.  
  417. //----------------------------------------------------------------------------------------
  418. //    FW_CPrivBitmapRep::Write
  419. //----------------------------------------------------------------------------------------
  420.  
  421. void FW_CPrivBitmapRep::Write(FW_CWritableStream& stream, FW_Boolean bDIBFileHeader)
  422. {
  423. #ifdef FW_BUILD_MAC
  424.     // Lock the GWorld pixmap
  425.     FW_CPrivMacPixelLock lock(this);
  426.     PixMapHandle pmh = lock.GetPixMapHandle();
  427.  
  428.     short        width        = (*pmh)->bounds.right;
  429.     short        height         = (*pmh)->bounds.bottom;
  430.     short        bitDepth    = (*pmh)->pixelSize;
  431.     
  432.     short        resRowBytes    = ((width * bitDepth + 31) & ~31) / 8;
  433.     short        memRowBytes    = (*pmh)->rowBytes & 0x7FFF;
  434.  
  435.     FW_ASSERT(resRowBytes <= memRowBytes);
  436.  
  437.     long imageSize = height * resRowBytes;
  438.  
  439.     // Determine color table size
  440.     int colorTableCount = bitDepth < 16 ? 1 << bitDepth : 0;
  441.     int colorTableSize  = colorTableCount * sizeof(RGBQUAD);
  442.  
  443.     // Create a file header
  444.     if(bDIBFileHeader)
  445.     {
  446.         BITMAPFILEHEADER bmfh;
  447.         bmfh.bfType                = FW_kWinBitmapSignature;
  448.         bmfh.bfSize                = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
  449.                                 colorTableSize + imageSize;
  450.         bmfh.bfReserved1        = 0;
  451.         bmfh.bfReserved2        = 0;
  452.         bmfh.bfOffBits            = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
  453.                                 colorTableSize;
  454.         
  455.         // Byte-swap and write it out
  456.         
  457.         MacRepackValue(&bmfh.bfType);
  458.         MacRepackValue(&bmfh.bfSize);
  459.         MacRepackValue(&bmfh.bfReserved1);
  460.         MacRepackValue(&bmfh.bfReserved2);
  461.         MacRepackValue(&bmfh.bfOffBits);
  462.         
  463.         stream.Write(&bmfh, sizeof(bmfh));
  464.     }
  465.  
  466.     // Create a DIB header
  467.  
  468.     BITMAPINFOHEADER bmih;
  469.  
  470.     bmih.biSize                = sizeof(BITMAPINFOHEADER);
  471.     bmih.biWidth            = width;
  472.     bmih.biHeight            = height;
  473.     bmih.biPlanes            = 1;
  474.     bmih.biBitCount            = bitDepth;
  475.     
  476.     bmih.biCompression        = 0;
  477.     bmih.biSizeImage        = imageSize;
  478.  
  479.     bmih.biXPelsPerMeter    = 0;
  480.     bmih.biYPelsPerMeter    = 0;
  481.     bmih.biClrUsed            = 0;
  482.     bmih.biClrImportant        = 0;
  483.     
  484.     // Byte-swap and write it out
  485.  
  486.     MacRepackValue(&bmih.biSize);
  487.     MacRepackValue(&bmih.biWidth);
  488.     MacRepackValue(&bmih.biHeight);
  489.     MacRepackValue(&bmih.biPlanes);
  490.     MacRepackValue(&bmih.biBitCount);
  491.     MacRepackValue(&bmih.biCompression);
  492.     MacRepackValue(&bmih.biSizeImage);
  493.     MacRepackValue(&bmih.biXPelsPerMeter);
  494.     MacRepackValue(&bmih.biYPelsPerMeter);
  495.     MacRepackValue(&bmih.biClrUsed);
  496.     MacRepackValue(&bmih.biClrImportant);
  497.  
  498.     stream.Write(&bmih, sizeof(bmih));
  499.  
  500.     // Write the color table (if applicable)
  501.     if(colorTableCount != 0)
  502.     {
  503.         CTabHandle cTabHandle = (*pmh)->pmTable;
  504.         FW_ASSERT(colorTableCount <= (*cTabHandle)->ctSize + 1);    // ctSize is count - 1!
  505.  
  506.         for(int i = 0; i < colorTableCount; ++i)
  507.         {
  508.             RGBQUAD quad;
  509.  
  510.             quad.rgbBlue        = (*cTabHandle)->ctTable[i].rgb.blue    >> 8;
  511.             quad.rgbGreen        = (*cTabHandle)->ctTable[i].rgb.green    >> 8;
  512.             quad.rgbRed            = (*cTabHandle)->ctTable[i].rgb.red        >> 8;
  513.             quad.rgbReserved    = 0;
  514.  
  515.             stream.Write(&quad, sizeof(quad));
  516.         }
  517.     }
  518.  
  519.     // Finally, do the bits (upside-down)
  520.     char* bitsBuffer = new char[memRowBytes];
  521.     
  522.     FW_TRY
  523.     {
  524.         const char* baseBuffer = ::GetPixBaseAddr(pmh);
  525.         const char* currBuffer = baseBuffer + memRowBytes * (height - 1);
  526.         
  527.         for(int row = height - 1; row >= 0; -- row, currBuffer -= memRowBytes)
  528.         {
  529.             ::BlockMove(currBuffer, bitsBuffer, resRowBytes);
  530.             MacRepackResourceRow(bitsBuffer, bitDepth, resRowBytes);
  531.             stream.Write(bitsBuffer, resRowBytes);
  532.         }
  533.     }
  534.     FW_CATCH_BEGIN
  535.     FW_CATCH_EVERYTHING()
  536.     {
  537.         delete[] bitsBuffer;
  538.         FW_THROW_SAME();
  539.     }
  540.     FW_CATCH_END
  541.     delete[] bitsBuffer;
  542. #endif
  543.  
  544. #ifdef FW_BUILD_WIN
  545.     // Convert to DIB first; use the color depth the user wanted
  546.     FW_WinDIB dib = FW_DIBConvertFromBitmap(fPlatformBitmap, fUserColorDepth, fWinPalette);
  547.     
  548.     FW_TRY
  549.     {
  550.         // Write out the DIB
  551.         FW_DIBSaveToStream(stream, dib, bDIBFileHeader);
  552.     }
  553.     FW_CATCH_BEGIN
  554.     FW_CATCH_EVERYTHING()
  555.     {
  556.         FW_DIBFree(dib);
  557.         FW_THROW_SAME();
  558.     }
  559.     FW_CATCH_END
  560.  
  561.     // Free the DIB
  562.     FW_DIBFree(dib);
  563. #endif
  564. }
  565.  
  566. //----------------------------------------------------------------------------------------
  567. //    FW_CPrivBitmapRep::FW_CPrivBitmapRep
  568. //----------------------------------------------------------------------------------------
  569. // From a stream: will own the bitmap
  570.  
  571. FW_CPrivBitmapRep::FW_CPrivBitmapRep(FW_CReadableStream& stream, FW_Boolean bDIBFileHeader) :
  572.     fOwnBitmap(TRUE),
  573.     fPlatformBitmap(NULL)
  574. {
  575. #ifdef FW_BUILD_MAC
  576.     fLockCount = 0;
  577.     fPixMapHandle = NULL;
  578. #endif
  579. #ifdef FW_BUILD_WIN
  580.     fUserColorDepth = 0;
  581.     fWinPalette = NULL;
  582. #endif
  583.  
  584.     PrivReadFromStream(stream, bDIBFileHeader);
  585. }
  586.  
  587. //----------------------------------------------------------------------------------------
  588. //    FW_CPrivBitmapRep::GetPlatformBitmap
  589. //----------------------------------------------------------------------------------------
  590.  
  591. FW_PlatformBitmap  FW_CPrivBitmapRep::GetPlatformBitmap() const
  592. {
  593.     return fPlatformBitmap;
  594. }
  595.  
  596. //----------------------------------------------------------------------------------------
  597. //    FW_CPrivBitmapRep::IsPlatformBitmapOrphan
  598. //----------------------------------------------------------------------------------------
  599.  
  600. FW_Boolean FW_CPrivBitmapRep::IsPlatformBitmapOrphan() const
  601. {
  602.     return !fOwnBitmap;
  603. }
  604.  
  605. //----------------------------------------------------------------------------------------
  606. //    FW_CPrivBitmapRep::OrphanPlatformBitmap
  607. //----------------------------------------------------------------------------------------
  608.  
  609. FW_PlatformBitmap  FW_CPrivBitmapRep::OrphanPlatformBitmap()
  610. {
  611.     FW_ASSERT(fOwnBitmap);        // Only orphan once
  612.     fOwnBitmap = FALSE;
  613.     return fPlatformBitmap;
  614. }
  615.  
  616. //----------------------------------------------------------------------------------------
  617. //    FW_CPrivBitmapRep::SetPlatformBitmap
  618. //----------------------------------------------------------------------------------------
  619.  
  620. void FW_CPrivBitmapRep::SetPlatformBitmap(FW_PlatformBitmap newBitmap)
  621. {
  622.     if (fPlatformBitmap != newBitmap)
  623.     {
  624.         PrivDisposeBitmap();
  625.         fPlatformBitmap = newBitmap;
  626.     }
  627.     
  628.     fOwnBitmap = FALSE;
  629. }
  630.  
  631. //----------------------------------------------------------------------------------------
  632. //    FW_CPrivBitmapRep::AdoptPlatformBitmap
  633. //----------------------------------------------------------------------------------------
  634.  
  635. void FW_CPrivBitmapRep::AdoptPlatformBitmap(FW_PlatformBitmap newBitmap)
  636. {
  637.     SetPlatformBitmap(newBitmap);
  638.     fOwnBitmap = TRUE;
  639. }
  640.  
  641. //----------------------------------------------------------------------------------------
  642. //    FW_CPrivBitmapRep::GetPalette
  643. //----------------------------------------------------------------------------------------
  644.  
  645. FW_Palette FW_CPrivBitmapRep::GetPalette() const
  646. {
  647. #ifdef FW_BUILD_MAC
  648.     FW_CPrivMacPixelLock lock((FW_HBitmap)this);
  649.     PixMapHandle pmh = lock.GetPixMapHandle();
  650.     return (*pmh)->pmTable;
  651. #endif
  652. #ifdef FW_BUILD_WIN
  653.     return fWinPalette;
  654. #endif
  655. }
  656.  
  657. //----------------------------------------------------------------------------------------
  658. //    FW_CPrivBitmapRep::SetPalette
  659. //----------------------------------------------------------------------------------------
  660.  
  661. void FW_CPrivBitmapRep::SetPalette(FW_Palette palette)
  662. {
  663. #ifdef FW_BUILD_MAC
  664.     FW_CPrivMacPixelLock lock(this);
  665.     PixMapHandle pmh = lock.GetPixMapHandle();
  666.     CTabHandle oldTable = (*pmh)->pmTable;
  667.     (*pmh)->pmTable = palette;
  668.     ::DisposeHandle((Handle)oldTable);
  669. #endif
  670. #ifdef FW_BUILD_WIN
  671.     if (fWinPalette != NULL)
  672.         ::DeleteObject(fWinPalette);
  673.     fWinPalette = palette;
  674. #endif
  675. }
  676.  
  677. //----------------------------------------------------------------------------------------
  678. //    FW_CPrivBitmapRep::GetBitmapInfo
  679. //----------------------------------------------------------------------------------------
  680.  
  681. void FW_CPrivBitmapRep::GetBitmapInfo(
  682.         short& width,
  683.         short& height,
  684.         short& rowBytes,
  685.         short& pixelSize) const
  686. {
  687. #ifdef FW_BUILD_MAC
  688.     PixMapHandle pixMap = ::GetGWorldPixMap(fPlatformBitmap);
  689.  
  690.     width        = (*pixMap)->bounds.right - (*pixMap)->bounds.left;
  691.     height        = (*pixMap)->bounds.bottom - (*pixMap)->bounds.top;
  692.     rowBytes    = (*pixMap)->rowBytes & 0x7FFF;
  693.     pixelSize    = (*pixMap)->pixelSize;
  694. #endif
  695.  
  696. #ifdef FW_BUILD_WIN
  697.     BITMAP bm;
  698.     ::GetObject(fPlatformBitmap, sizeof(bm), &bm);
  699.  
  700.     width        = (short) bm.bmWidth;
  701.     height        = (short) bm.bmHeight;
  702.     rowBytes    = (short) bm.bmWidthBytes;
  703.     pixelSize    = fUserColorDepth;            // The actual DDB pixel size may differ
  704. #endif
  705. }
  706.  
  707. //----------------------------------------------------------------------------------------
  708. //    FW_CPrivBitmapRep::GetBitmapBoundsGC
  709. //----------------------------------------------------------------------------------------
  710.  
  711. void FW_CPrivBitmapRep::GetBitmapBoundsGC(Environment* ev, FW_SGraphicContext& gc, FW_SRect& bounds) const
  712. {
  713.     short width, height,rowBytes, pixelSize;
  714.     GetBitmapInfo(width, height, rowBytes, pixelSize);
  715.         
  716.     FW_CPoint size;
  717.     FW_PrivGC_DeviceToLogicalSize(ev, gc, width, height, size);
  718.     // let go if error
  719.     
  720.     bounds.left        = FW_kFixed0;
  721.     bounds.top        = FW_kFixed0;
  722.     bounds.right    = size.x;
  723.     bounds.bottom    = size.y;
  724. }
  725.  
  726. //----------------------------------------------------------------------------------------
  727. //    FW_CPrivBitmapRep::GetBitmapBounds
  728. //----------------------------------------------------------------------------------------
  729.  
  730. void FW_CPrivBitmapRep::GetBitmapBounds(FW_SRect& bounds) const
  731. {
  732.     short width, height,rowBytes, pixelSize;
  733.     GetBitmapInfo(width, height, rowBytes, pixelSize);
  734.  
  735.     bounds.left     = FW_IntToFixed(0);
  736.     bounds.top        = FW_IntToFixed(0);
  737.     bounds.right    = FW_IntToFixed(width);
  738.     bounds.bottom    = FW_IntToFixed(height);
  739. }
  740.  
  741. //----------------------------------------------------------------------------------------
  742. //    FW_CPrivBitmapRep::GetPixelColor
  743. //----------------------------------------------------------------------------------------
  744.  
  745. void FW_CPrivBitmapRep::GetPixelColor(short horiz,
  746.                                     short vert,
  747.                                     FW_CColor& color) const
  748. {
  749. #ifdef FW_BUILD_MAC
  750.     RGBColor    platformColor;
  751.     
  752.     {
  753.         FW_PrivSetRestoreGWorld saveRestore(fPlatformBitmap);
  754.         ::GetCPixel(horiz, vert, &platformColor);
  755.     }
  756.     
  757.     color = platformColor;
  758. #endif
  759.     
  760. #ifdef FW_BUILD_WIN
  761.         // needs to be implemented
  762. #endif
  763. }
  764.  
  765. //----------------------------------------------------------------------------------------
  766. //    FW_CPrivBitmapRep::SetPixelColor
  767. //----------------------------------------------------------------------------------------
  768.  
  769. void FW_CPrivBitmapRep::SetPixelColor(short horiz,
  770.                                     short vert,
  771.                                     const FW_CColor& color)
  772. {
  773. #ifdef FW_BUILD_MAC
  774.     RGBColor    platformColor(color);
  775.     {
  776.         FW_PrivSetRestoreGWorld saveRestore(fPlatformBitmap);
  777.         ::SetCPixel(horiz, vert, &platformColor);
  778.     }
  779. #endif
  780.  
  781. #ifdef FW_BUILD_WIN
  782.         // needs to be implemented
  783. #endif
  784. }
  785.  
  786. //----------------------------------------------------------------------------------------
  787. //    FW_CPrivBitmapRep::ChangeBitmap
  788. //----------------------------------------------------------------------------------------
  789.  
  790. FW_PlatformError FW_CPrivBitmapRep::ChangeBitmap(short         width,
  791.                                     short         height,
  792.                                     short         pixelSize,
  793.                                     FW_Boolean     bScale,
  794.                                     FW_Palette    palette)
  795. {
  796.     FW_PlatformError error = FW_xNoError;
  797.     
  798. #ifdef FW_BUILD_MAC
  799.     FW_ASSERT(!MacIsPixelsLocked());
  800.     FW_CPlatformRect boundsRect(0, 0, width, height);
  801.     GWorldFlags flags = ::UpdateGWorld(&fPlatformBitmap, pixelSize, &boundsRect, palette, NULL, bScale ? stretchPix : clipPix);
  802.     if (flags == gwFlagErr)
  803.         error = FW_xGraphicException;
  804. #endif
  805.  
  806. #ifdef FW_BUILD_WIN
  807.     // Determine color depth for the DDB
  808.     short bmNewPlanes = 1, bmNewBitsPixel = 1;
  809.     if(pixelSize != 1)
  810.         FW_PrivWinGetDisplayColorInfo(bmNewPlanes, bmNewBitsPixel);
  811.         
  812.     // Get the current bitmap depth
  813.     BITMAP bm;
  814.     ::GetObject(fPlatformBitmap, sizeof(bm), &bm);
  815.     
  816.     if(bm.bmPlanes != bmNewPlanes || bm.bmBitsPixel != bmNewBitsPixel ||
  817.         bm.bmWidth != width || bm.bmHeight != height)
  818.     {
  819.         // Create a new bitmap        
  820.         HBITMAP bitmap = ::CreateBitmap(width, height, bmNewPlanes, bmNewBitsPixel, NULL);
  821.         if(bitmap != NULL)
  822.         {
  823.             // Copy the bits
  824.             FW_CPlatformRect rectSrc(0, 0, bm.bmWidth, bm.bmHeight);
  825.             FW_CPlatformRect rectDst(0, 0, width, height);
  826.             FW_DDBCopyImage(
  827.                 bitmap, NULL, &rectDst,                 // Even if fWinPalette is not NULL,
  828.                 fPlatformBitmap, NULL, &rectSrc,        //  no color translation is needed here
  829.                 bScale
  830.                     ? FW_kScaleImage
  831.                     : FW_kCropImage);
  832.     
  833.             // Replace the platform bitmap
  834.             AdoptPlatformBitmap(bitmap);
  835.         }
  836.         else
  837.         {
  838.             error = FW_xGraphicException;
  839.         }
  840.     }
  841.  
  842.     // Update the color depth
  843.     if(pixelSize != 0 && error == FW_xNoError)
  844.         fUserColorDepth = pixelSize;
  845.     else
  846.         fUserColorDepth = FW_DDBGetColorDepth(fPlatformBitmap);
  847. #endif
  848.  
  849.     return error;
  850. }
  851.  
  852. //----------------------------------------------------------------------------------------
  853. //    FW_CPrivBitmapRep::ChangeBitmap
  854. //----------------------------------------------------------------------------------------
  855.  
  856. FW_PlatformError FW_CPrivBitmapRep::ChangeBitmap(void*         image,
  857.                                     long         imageSize,
  858.                                     short        rowBytes,
  859.                                     short         width,
  860.                                     short         height,
  861.                                     short         pixelSize,
  862.                                     FW_Palette    palette)
  863. {    
  864.     const FW_Boolean bScale = FALSE;
  865.     FW_PlatformError error = ChangeBitmap(width, height, pixelSize, bScale, palette);
  866.     if (error == FW_xNoError)
  867.         error = SetImage(image, imageSize, rowBytes);
  868.     return error;
  869. }
  870.  
  871. //----------------------------------------------------------------------------------------
  872. //    FW_CPrivBitmapRep::SetImage
  873. //----------------------------------------------------------------------------------------
  874.  
  875. FW_PlatformError FW_CPrivBitmapRep::SetImage(void*     image,
  876.                                 long     imageSize,
  877.                                 short    rowBytes)
  878. {
  879.     short bmpHeight, bmpWidth, bmpRowBytes, bmpPixelSize;
  880.     GetBitmapInfo(bmpWidth, bmpHeight, bmpRowBytes, bmpPixelSize);
  881.  
  882.     FW_ASSERT(imageSize == 0 || image != NULL);
  883.     FW_ASSERT(rowBytes <= bmpRowBytes);
  884.  
  885. #ifdef FW_BUILD_MAC
  886.     FW_CPrivMacPixelLock lock(this);
  887.     PixMapHandle pmh = lock.GetPixMapHandle();
  888.     Ptr baseAddr = ::GetPixBaseAddr(pmh);
  889.     
  890.     if (rowBytes == bmpRowBytes)
  891.     {
  892.         size_t toCopy = bmpHeight * bmpRowBytes;
  893.         if (toCopy > imageSize)
  894.             toCopy = imageSize;
  895.  
  896.         FW_PrimitiveCopyMemory(image, baseAddr, toCopy);
  897.     }
  898.     else
  899.     {
  900.         const char* srcPtr = (const char*) image;
  901.         char* dstPtr = baseAddr;
  902.         
  903.         for (
  904.             int nRow = 0;
  905.             nRow < bmpHeight && imageSize > 0;
  906.             ++nRow, imageSize -= rowBytes, srcPtr += rowBytes, dstPtr += bmpRowBytes
  907.             )
  908.             FW_PrimitiveCopyMemory(srcPtr, dstPtr, rowBytes);
  909.     }
  910. #endif
  911.  
  912. #ifdef FW_BUILD_WIN
  913.     if (rowBytes == bmpRowBytes)
  914.     {
  915.         ::SetBitmapBits(fPlatformBitmap, imageSize, image);
  916.     }
  917.     else
  918.     {
  919.         int nRowCount = imageSize / rowBytes;
  920.         FW_CAcquireTemporaryMemory tempMem(nRowCount * bmpRowBytes);
  921.         
  922.         const char* srcPtr = (const char*) image;
  923.         char* dstPtr = (char*) tempMem.GetPointer();
  924.  
  925.         for (
  926.             int nRow = 0;
  927.             nRow < bmpHeight && imageSize > 0;
  928.             ++nRow, imageSize -= rowBytes, srcPtr += rowBytes, dstPtr += bmpRowBytes
  929.             )
  930.             FW_PrimitiveCopyMemory(srcPtr, dstPtr, rowBytes);
  931.  
  932.         ::SetBitmapBits(fPlatformBitmap, nRowCount * bmpRowBytes, tempMem.GetPointer());
  933.     }
  934. #endif
  935.  
  936.     return FW_xNoError;
  937. }
  938.  
  939. //----------------------------------------------------------------------------------------
  940. //    FW_CPrivBitmapRep::CopyPixels
  941. //----------------------------------------------------------------------------------------
  942.  
  943. FW_PlatformError FW_CPrivBitmapRep::CopyPixels(FW_CPrivBitmapRep& dstBitmap, 
  944.                                     const FW_SRect& boundsSrc, 
  945.                                     const FW_SRect& boundsDst) const
  946. {
  947.     FW_RETURN_ERR_TRY
  948.     {
  949.         FW_CPlatformRect plfmSrcRect = boundsSrc;
  950.         FW_CPlatformRect plfmDstRect = boundsDst;
  951.  
  952. #ifdef FW_BUILD_MAC
  953.         FW_CPrivMacPixelLock srcLock((FW_HBitmap)this);
  954.         PixMapHandle srcPixMap = srcLock.GetPixMapHandle();
  955.     
  956.         FW_CPrivMacPixelLock dstLock(&dstBitmap);
  957.         PixMapHandle dstPixMap = dstLock.GetPixMapHandle();
  958.         
  959.         {
  960.             FW_PrivSetRestoreGWorld saveRestore(dstBitmap.GetPlatformBitmap());
  961.             ::CopyBits((BitMap*)*srcPixMap, (BitMap*)*dstPixMap,  
  962.                         &plfmSrcRect, &plfmDstRect, 
  963.                         srcCopy, NULL);
  964.         }
  965. #endif
  966. #ifdef FW_BUILD_WIN
  967.         HBITMAP dstBitmapHandle = dstBitmap.GetPlatformBitmap();
  968.         HPALETTE hDstPalette = dstBitmap.GetPalette();
  969.     
  970.         FW_DDBCopyImage(dstBitmapHandle, hDstPalette, &plfmDstRect,
  971.                         fPlatformBitmap, fWinPalette, &plfmSrcRect,
  972.                         FW_kScaleImage);
  973. #endif
  974.     }
  975.     FW_RETURN_ERR_CATCH
  976. }
  977.  
  978. #ifdef FW_BUILD_MAC
  979.  
  980. //----------------------------------------------------------------------------------------
  981. //    FW_CPrivBitmapRep::FW_CPrivBitmapRep
  982. //----------------------------------------------------------------------------------------
  983. // From a picture: will own the bitmap
  984.  
  985. FW_CPrivBitmapRep::FW_CPrivBitmapRep(FW_HPicture picture, FW_SColor fillColor, const FW_SRect& pictPart) :
  986.     fOwnBitmap(TRUE),
  987.     fPlatformBitmap(NULL)
  988. {
  989. #ifdef FW_BUILD_MAC
  990.     fLockCount = 0;
  991.     fPixMapHandle = NULL;
  992. #endif
  993. #ifdef FW_BUILD_WIN
  994.     fUserColorDepth = 0;
  995.     fWinPalette = NULL;
  996. #endif
  997.  
  998.     //    It looks like I have to be in a 'valid' port before calling GetPictInfo
  999.     //    I we don't set a valid port we end up with color problems.
  1000.     CGrafPtr screenPort;
  1001.     GetCWMgrPort(&screenPort);
  1002.  
  1003.     {
  1004.         // save the port, and set it to a valid port
  1005.         FW_PrivSetRestoreGWorld saveRestore(screenPort);
  1006.  
  1007.         FW_PlatformPict pictHandle = picture->GetPlatformPict();
  1008.         FW_ASSERT(pictHandle != 0);
  1009.  
  1010.         PictInfo pictInfo;
  1011.         pictInfo.theColorTable = nil;
  1012.         
  1013.         // Just get color depth    at first
  1014.         FW_FailOnError(::GetPictInfo(pictHandle, &pictInfo, 0, 0, systemMethod, 0));
  1015.  
  1016.         // !!! [BRP] A QuickTime-compressed picture will return pictInfo.depth == 1,
  1017.         // so we might end up displaying a 1-bit bitmap for a deeper picture.
  1018.         
  1019.         if(pictInfo.depth > 8)
  1020.         {
  1021.             pictInfo.theColorTable = NULL;
  1022.         }
  1023.         else
  1024.         {    
  1025.             // Now that we know the color depth, we are ready to get the color table
  1026.             
  1027.             // we only do this for depth <= 8 because that's the only time we need it, and it's
  1028.             // quite time-consuming on large pictures
  1029.             
  1030.             short nColors = 1 << pictInfo.depth;
  1031.             // medianMethod is better than popularMethod, but it's really slow
  1032.             // systemMethod is, by default, popularMethod
  1033.             FW_FailOnError(::GetPictInfo(pictHandle, &pictInfo, returnColorTable, nColors, systemMethod, 0));
  1034.         }
  1035.  
  1036.         FW_CPlatformRect gworldRect = pictPart;
  1037.         ::OffsetRect(&gworldRect, -gworldRect.left, -gworldRect.top);
  1038.  
  1039.         // Create a GWorld
  1040.         QDErr err = ::NewGWorld(&fPlatformBitmap, pictInfo.depth, &gworldRect,
  1041.                 pictInfo.theColorTable, NULL, useTempMem);
  1042.  
  1043.         if(pictInfo.theColorTable)
  1044.             ::DisposeCTable(pictInfo.theColorTable);
  1045.  
  1046.         FW_FailOnError(err);
  1047.         
  1048.         if(fPlatformBitmap == NULL) // most likely FW_FailOnError would have caught this
  1049.             FW_Failure(FW_xGraphicException);
  1050.             
  1051.         // Draw the picture to the gworld. We already saved the old GWorld on entry
  1052.         
  1053.         {
  1054.             FW_CPrivMacPixelLock lock(this);
  1055.  
  1056.             ::SetGWorld(fPlatformBitmap, NULL);
  1057.             ::ClipRect(&gworldRect);
  1058.             
  1059.             // erase with the fill color in case the picture doesn't
  1060.             // completely cover thebackground
  1061.             RGBColor macColor = FW_CColor(fillColor);
  1062.             ::RGBBackColor(&macColor);
  1063.             ::EraseRect(&gworldRect);
  1064.             FW_PrivMacSetStdColors();
  1065.             
  1066.             // get the actual rect of the picture
  1067.             FW_CPlatformRect rectPicture = pictInfo.sourceRect;
  1068.             
  1069.             // offset by the portion of the picture we want to grab
  1070.             // (similar to what one would do with SetOrigin or combined transforms)
  1071.             ::OffsetRect(&rectPicture, - FW_FixedToInt(pictPart.left), - FW_FixedToInt(pictPart.top));
  1072.             
  1073.             ::DrawPicture(pictHandle, &rectPicture);
  1074.         }
  1075.         
  1076.         // gworld will be restored when stack object is destroyed
  1077.     }
  1078.     
  1079.     FW_END_CONSTRUCTOR
  1080. }
  1081. #endif
  1082.  
  1083. #ifdef FW_BUILD_MAC
  1084. //----------------------------------------------------------------------------------------
  1085. //    FW_CPrivBitmapRep::MacGetAsPicture
  1086. //----------------------------------------------------------------------------------------
  1087.  
  1088. FW_HPicture FW_CPrivBitmapRep::MacGetAsPicture(const FW_SRect& bounds) const
  1089. {    
  1090.     // set the port to our own gworld, open a picture, copybits to ourself,
  1091.     // close the picture, and return it.
  1092.     
  1093.     FW_CPlatformRect plfmSrcRect = bounds;
  1094.     FW_CPlatformRect plfmDstRect = bounds;
  1095.     ::OffsetRect(&plfmDstRect, -plfmDstRect.left, -plfmDstRect.top);
  1096.  
  1097.     OpenCPicParams openParams;
  1098.     openParams.srcRect    = plfmDstRect;
  1099.     openParams.hRes        =
  1100.     openParams.vRes     = 0x00480000;
  1101.     openParams.version    = -2; // always set to -2, per Inside Macintosh
  1102.     openParams.reserved1 =
  1103.     openParams.reserved2 = 0;
  1104.  
  1105.     PicHandle hPict;
  1106.     
  1107.     {
  1108.         FW_CPrivMacPixelLock lock((FW_HBitmap)this);
  1109.         FW_PrivSetRestoreGWorld setRestore(fPlatformBitmap);
  1110.         
  1111. //        FW_CSetHeapZone tempZone(::SystemZone());
  1112.  
  1113.         hPict = ::OpenCPicture(&openParams);
  1114.  
  1115.         PixMapHandle pixMap = lock.GetPixMapHandle();
  1116.         
  1117.         ::CopyBits((BitMap*)*pixMap, (BitMap*)*pixMap,  
  1118.                     &plfmSrcRect, &plfmDstRect, 
  1119.                     srcCopy, NULL);
  1120.                     
  1121.         ::ClosePicture();
  1122.     }
  1123.     
  1124.     return FW_NEW(FW_CPrivPictureRep, (hPict));
  1125. }
  1126.  
  1127. #endif
  1128.  
  1129. #ifdef FW_BUILD_MAC
  1130.  
  1131. //----------------------------------------------------------------------------------------
  1132. //    FW_CPrivBitmapRep::MacLockPixels
  1133. //----------------------------------------------------------------------------------------
  1134.  
  1135. PixMapHandle FW_CPrivBitmapRep::MacLockPixels()
  1136. {
  1137.     if (++ fLockCount == 1)
  1138.     {
  1139.         FW_ASSERT(fPixMapHandle == NULL);
  1140.         fPixMapHandle = ::GetGWorldPixMap(fPlatformBitmap);
  1141.         Boolean locked = ::LockPixels(fPixMapHandle);
  1142.         FW_ASSERT(locked); // should always be true since we never allocate purgeable gworld pixels
  1143.     }
  1144.  
  1145.     return fPixMapHandle;
  1146. }
  1147. #endif
  1148.  
  1149. #ifdef FW_BUILD_MAC
  1150.  
  1151. //----------------------------------------------------------------------------------------
  1152. //    FW_CPrivBitmapRep::MacUnlockPixels
  1153. //----------------------------------------------------------------------------------------
  1154.  
  1155. void FW_CPrivBitmapRep::MacUnlockPixels()
  1156. {
  1157.     FW_ASSERT(fPixMapHandle != NULL);
  1158.     FW_ASSERT(fLockCount != 0);
  1159.     
  1160.     if (-- fLockCount == 0)
  1161.     {
  1162.         ::UnlockPixels(fPixMapHandle);    
  1163.         fPixMapHandle = NULL;
  1164.     }
  1165. }
  1166. #endif
  1167.  
  1168. #ifdef FW_BUILD_MAC
  1169. //----------------------------------------------------------------------------------------
  1170. //    FW_CPrivBitmapRep::MacIsPixelsLocked
  1171. //----------------------------------------------------------------------------------------
  1172.  
  1173. FW_Boolean FW_CPrivBitmapRep::MacIsPixelsLocked() const
  1174. {
  1175.     return fLockCount != 0;
  1176. }
  1177. #endif
  1178.  
  1179. //----------------------------------------------------------------------------------------
  1180. //    FW_CPrivBitmapRep::PrivDisposeBitmap
  1181. //----------------------------------------------------------------------------------------
  1182.  
  1183. void FW_CPrivBitmapRep::PrivDisposeBitmap()
  1184. {
  1185.     if (fOwnBitmap && fPlatformBitmap != NULL)
  1186.     {
  1187. #ifdef FW_BUILD_MAC
  1188.         ::DisposeGWorld(fPlatformBitmap);
  1189. #endif
  1190. #ifdef FW_BUILD_WIN
  1191.         ::DeleteObject(fPlatformBitmap);
  1192.         
  1193.         if (fWinPalette != NULL)
  1194.         {
  1195.             ::DeleteObject(fWinPalette);
  1196.             fWinPalette = NULL;
  1197.         }
  1198. #endif
  1199.     }
  1200.  
  1201.     fPlatformBitmap = NULL;
  1202.     fOwnBitmap = FALSE;
  1203. }
  1204.  
  1205. //----------------------------------------------------------------------------------------
  1206. //    FW_CPrivBitmapRep::PrivMakeBitmap
  1207. //----------------------------------------------------------------------------------------
  1208.  
  1209. void FW_CPrivBitmapRep::PrivMakeBitmap(
  1210.         short width, short height,
  1211.         short pixelSize, FW_Palette palette)
  1212. {
  1213.     FW_PlatformBitmap bitmap = NULL;
  1214.     
  1215.     FW_ASSERT(height != 0);
  1216.     FW_ASSERT(width != 0);
  1217.     
  1218. #ifdef FW_BUILD_MAC
  1219.     FW_CPlatformRect boundsRect(0, 0, width, height);
  1220.  
  1221.     OSErr err = ::NewGWorld(&bitmap, pixelSize, &boundsRect, palette, NULL, useTempMem);
  1222.     FW_FailOnError(err);
  1223. #endif
  1224. #ifdef FW_BUILD_WIN
  1225.     // Determine color depth for the DDB
  1226.     short bmPlanes = 1, bmBitsPixel = 1;
  1227.     if(pixelSize != 1)
  1228.         FW_PrivWinGetDisplayColorInfo(bmPlanes, bmBitsPixel);
  1229.  
  1230.     // Create the bitmap    
  1231.     bitmap = ::CreateBitmap(width, height, bmPlanes, bmBitsPixel, NULL);
  1232.     if(bitmap == NULL)
  1233.         FW_Failure(FW_xMemoryExhausted);
  1234.  
  1235.     // Update the color depth
  1236.     if(pixelSize != 0)
  1237.         fUserColorDepth = pixelSize;
  1238.     else
  1239.         fUserColorDepth = FW_DDBGetColorDepth(bitmap);
  1240.         
  1241.     // Copy the palette if there is one
  1242.     if (palette != NULL)
  1243.         fWinPalette = FW_CopyPalette(palette);
  1244. #endif
  1245.  
  1246.     fPlatformBitmap    = bitmap;
  1247.     fOwnBitmap    = TRUE;
  1248. }
  1249.  
  1250. //----------------------------------------------------------------------------------------
  1251. //    FW_CPrivBitmapRep::PrivReadFromStream
  1252. //----------------------------------------------------------------------------------------
  1253.  
  1254. void FW_CPrivBitmapRep::PrivReadFromStream(FW_CReadableStream& stream, FW_Boolean bDIBFileHeader)
  1255. {
  1256. #ifdef FW_BUILD_WIN
  1257.     FW_WinDIB dib = FW_DIBLoadFromStream(stream, bDIBFileHeader);
  1258.     
  1259.     // Get the palette
  1260.     fWinPalette = FW_DIBGetPalette(dib);
  1261.  
  1262.     FW_TRY
  1263.     {
  1264.         fPlatformBitmap = FW_DIBConvertToBitmap(dib, fWinPalette);
  1265.     }
  1266.     FW_CATCH_BEGIN
  1267.     FW_CATCH_EVERYTHING()
  1268.     {
  1269.         FW_DIBFree(dib);
  1270.         FW_THROW_SAME();
  1271.     }
  1272.     FW_CATCH_END
  1273.     
  1274.     FW_DIBFree(dib);
  1275.  
  1276.     // Update the color depth
  1277.     fUserColorDepth = FW_DDBGetColorDepth(fPlatformBitmap);
  1278. #endif
  1279.  
  1280. #ifdef FW_BUILD_MAC
  1281.     // Read the BITMAPFILEINFO header
  1282.     if(bDIBFileHeader)
  1283.     {
  1284.         BITMAPFILEHEADER bmfh;
  1285.         
  1286.         stream.Read((void*) &bmfh, sizeof(bmfh));
  1287.         
  1288.         MacRepackValue(&bmfh.bfType);
  1289.         MacRepackValue(&bmfh.bfSize);
  1290.         MacRepackValue(&bmfh.bfReserved1);
  1291.         MacRepackValue(&bmfh.bfReserved2);
  1292.         MacRepackValue(&bmfh.bfOffBits);
  1293.     
  1294.         if(bmfh.bfType != FW_kWinBitmapSignature || bmfh.bfReserved1 != 0 || bmfh.bfReserved2 != 0)        
  1295.             FW_Failure(FW_xInvalidBitmapData);
  1296.     }
  1297.  
  1298.     // Start reading the header
  1299.     FW_Boolean bIsWindowsBitmap;
  1300.     BITMAPINFOHEADER bmih;
  1301.  
  1302.     stream.Read((void*) &bmih.biSize, sizeof(bmih.biSize));
  1303.  
  1304.     MacRepackValue(&bmih.biSize);
  1305.  
  1306.     if(bmih.biSize == sizeof(BITMAPINFOHEADER))                // Windows bitmap
  1307.     {
  1308.         // Read the Windows header
  1309.         stream.Read((void*) &bmih.biWidth, sizeof(bmih) - sizeof(bmih.biSize));
  1310.         
  1311.         MacRepackValue(&bmih.biWidth);
  1312.         MacRepackValue(&bmih.biHeight);
  1313.         MacRepackValue(&bmih.biPlanes);
  1314.         MacRepackValue(&bmih.biBitCount);
  1315.         MacRepackValue(&bmih.biCompression);
  1316.         MacRepackValue(&bmih.biSizeImage);
  1317.         MacRepackValue(&bmih.biXPelsPerMeter);
  1318.         MacRepackValue(&bmih.biYPelsPerMeter);
  1319.         MacRepackValue(&bmih.biClrUsed);
  1320.         MacRepackValue(&bmih.biClrImportant);
  1321.  
  1322.         bIsWindowsBitmap = TRUE;
  1323.     }
  1324.     else if(bmih.biSize == sizeof(BITMAPCOREHEADER))        // OS/2 bitmap
  1325.     {
  1326.         // Read the OS/2 header
  1327.         BITMAPCOREHEADER bmch;
  1328.         
  1329.         stream.Read((void* )&bmch.bcWidth, sizeof(bmch) - sizeof(bmch.bcSize));
  1330.  
  1331.         MacRepackValue(&bmch.bcWidth);
  1332.         MacRepackValue(&bmch.bcHeight);
  1333.         MacRepackValue(&bmch.bcPlanes);
  1334.         MacRepackValue(&bmch.bcBitCount);
  1335.  
  1336.         // Plug the data into the Windows header
  1337.         bmih.biWidth            =    bmch.bcWidth;
  1338.         bmih.biHeight            =    bmih.biHeight;
  1339.         bmih.biPlanes            =    bmch.bcPlanes;
  1340.         bmih.biBitCount            =    bmch.bcBitCount;
  1341.         bmih.biCompression        =    0;
  1342.         bmih.biSizeImage        =    0;
  1343.         bmih.biXPelsPerMeter    =    0;
  1344.         bmih.biYPelsPerMeter    =    0;
  1345.         bmih.biClrUsed            =    0;
  1346.         bmih.biClrImportant        =    0;
  1347.  
  1348.         bIsWindowsBitmap = FALSE;
  1349.     }
  1350.     else
  1351.         FW_Failure(FW_xInvalidBitmapData);
  1352.  
  1353.     // Check for compression flag -- we don't support it!
  1354.     if(bmih.biCompression != 0)
  1355.         FW_Failure(FW_xInvalidBitmapData);
  1356.  
  1357.     // Determine the size of the color table
  1358.     short bitDepth = bmih.biBitCount;
  1359.     short colorCount = bmih.biClrUsed != 0 ? bmih.biClrUsed : bitDepth >= 16 ? 0 : (1 << bitDepth);
  1360.  
  1361.     // Read the color table
  1362.     CTabHandle colorTabHandle = NULL;
  1363.     if(colorCount != 0)
  1364.     {
  1365.         Size colorTableSize = sizeof(ColorTable) + sizeof(ColorSpec) * (colorCount - 1);
  1366.         FW_CAcquireTemporarySystemHandle colorTableMemory(colorTableSize);
  1367.         CTabPtr colorTablePtr = (CTabPtr) colorTableMemory.GetPointer();
  1368.  
  1369.         for(int i = 0; i < colorCount; colorTablePtr->ctTable[i].value = i, ++i)
  1370.         {
  1371.             if(bIsWindowsBitmap)
  1372.             {
  1373.                 RGBQUAD quad;
  1374.                 stream.Read((void*) &quad, sizeof(quad));
  1375.                     
  1376.                 colorTablePtr->ctTable[i].rgb.red    = (quad.rgbRed        << 8) | quad.rgbRed;
  1377.                 colorTablePtr->ctTable[i].rgb.green    = (quad.rgbGreen    << 8) | quad.rgbGreen;
  1378.                 colorTablePtr->ctTable[i].rgb.blue    = (quad.rgbBlue        << 8) | quad.rgbBlue;
  1379.             }
  1380.             else
  1381.             {
  1382.                 RGBTRIPLE trip;
  1383.                 stream.Read((void*) &trip, sizeof(trip));
  1384.                     
  1385.                 colorTablePtr->ctTable[i].rgb.red    = trip.rgbtRed    << 8;
  1386.                 colorTablePtr->ctTable[i].rgb.green    = trip.rgbtGreen<< 8;
  1387.                 colorTablePtr->ctTable[i].rgb.blue    = trip.rgbtBlue    << 8;
  1388.             }
  1389.         }
  1390.  
  1391.         colorTablePtr->ctSeed    = 0;
  1392.         colorTablePtr->ctFlags    = 0;
  1393.         colorTablePtr->ctSize    = colorCount - 1;
  1394.  
  1395.         colorTabHandle = (CTabHandle) colorTableMemory.Orphan();
  1396.         
  1397.         ::CTabChanged(colorTabHandle);
  1398.     }
  1399.  
  1400.     // Create a GWorld
  1401.     FW_CPlatformRect bounds(0, 0, bmih.biWidth, bmih.biHeight);
  1402.     OSErr err = ::NewGWorld(&fPlatformBitmap, bitDepth, &bounds,
  1403.         colorTabHandle, NULL, useTempMem);
  1404.  
  1405.     if (colorTabHandle != NULL)
  1406.         ::DisposeCTable(colorTabHandle);
  1407.  
  1408.     FW_FailOnError(err);
  1409.  
  1410.     // Lock the memory pixmap
  1411.     FW_CPrivMacPixelLock lock(this);
  1412.     PixMapHandle memPixMap = lock.GetPixMapHandle();
  1413.     void* memBaseAddr = ::GetPixBaseAddr(memPixMap);
  1414.  
  1415.     // Read the bits
  1416.     short resRowBytes = ((bmih.biWidth * bitDepth + 31) & ~31) / 8;
  1417.     short memRowBytes = (*memPixMap)->rowBytes & 0x7FFF;
  1418.     FW_ASSERT(resRowBytes <= memRowBytes);
  1419.  
  1420.     char* curBuffer    = (char*) memBaseAddr + (bmih.biHeight - 1) * memRowBytes;
  1421.     
  1422.     for(int row = bmih.biHeight - 1; row >= 0; -- row, curBuffer -= memRowBytes)
  1423.     {
  1424.         // Read and repack the next row
  1425.         stream.Read(curBuffer, resRowBytes);
  1426.         MacRepackResourceRow(curBuffer, bitDepth, resRowBytes);
  1427.     }
  1428. #endif
  1429. }
  1430.  
  1431. #ifdef FW_BUILD_MAC
  1432.  
  1433. //========================================================================================
  1434. // CLASS FW_CPrivMacPixelLock
  1435. //========================================================================================
  1436.  
  1437. FW_DEFINE_AUTO(FW_CPrivMacPixelLock)
  1438.  
  1439. //----------------------------------------------------------------------------------------
  1440. // FW_CPrivMacPixelLock::FW_CPrivMacPixelLock
  1441. //----------------------------------------------------------------------------------------
  1442.  
  1443. FW_CPrivMacPixelLock::FW_CPrivMacPixelLock(FW_HBitmap rep) :
  1444.     fBitmap(rep)
  1445. {
  1446.     fPixMapHandle = FW_PrivBitmap_MacLockPixels(fBitmap);
  1447.  
  1448.     FW_END_CONSTRUCTOR
  1449. }
  1450.  
  1451. //----------------------------------------------------------------------------------------
  1452. // FW_CPrivMacPixelLock::~FW_CPrivMacPixelLock
  1453. //----------------------------------------------------------------------------------------
  1454.  
  1455. FW_CPrivMacPixelLock::~FW_CPrivMacPixelLock()
  1456. {
  1457.     FW_START_DESTRUCTOR
  1458.  
  1459.     FW_PrivBitmap_MacUnlockPixels(fBitmap);
  1460. }
  1461.  
  1462. //----------------------------------------------------------------------------------------
  1463. // FW_CPrivMacPixelLock::GetPixMapHandle
  1464. //----------------------------------------------------------------------------------------
  1465.  
  1466. PixMapHandle FW_CPrivMacPixelLock::GetPixMapHandle() const
  1467. {
  1468.     FW_ASSERT(fBitmap->MacIsPixelsLocked());
  1469.     return fPixMapHandle;
  1470. }
  1471.  
  1472. #endif
  1473.