home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / Sources / FWBitmap.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  41.0 KB  |  1,482 lines  |  [TEXT/MPS ]

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