home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / DIB.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  20.9 KB  |  740 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1992, 1993 by Borland International
  3. //   source\owl\dib.cpp
  4. //   Implementation of TDib class
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\gdiobjec.h>
  9. #include <owl\metafile.h>
  10. #include <owl\clipboar.h>
  11. #include <owl\except.h>
  12. #include <classlib\file.h>
  13.  
  14. //
  15. // size of scan in bytes =
  16. //   Pixel Width * bits per pixel rounded up to a DWORD boundary
  17. //
  18. inline long ScanBytes(int pixWidth, int bitsPixel) {
  19.   return (((long)pixWidth*bitsPixel+31) / 32) * 4;
  20. }
  21.  
  22. DIAG_DECLARE_GROUP(OwlGDI);        // General GDI diagnostic group
  23.  
  24.  
  25. #if !defined(SECTION) || SECTION == 1
  26.  
  27. // defining this will cause old core BMs to be converted to 3.0 format
  28. // undefine this to leave old core bms as is, or not worry about them at all
  29. //
  30. //#define CVT_CORE_TO_INFO
  31.  
  32.  
  33. //
  34. // Lock the global/res handle if needed & extract the pointers and cached info
  35. // maintained as member variables.
  36. //
  37. void
  38. TDib::InfoFromHandle()
  39. {
  40.   if (!Info)
  41.     if (IsResHandle)
  42.       Info = (LPBITMAPINFO)::LockResource(Handle);
  43.     else
  44.       Info = (LPBITMAPINFO)::GlobalLock(Handle);
  45.   if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  46.     IsCore = TRUE;
  47.   else if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
  48.     IsCore = FALSE;
  49.   else {
  50.     ::GlobalUnlock(Handle);
  51.     THROW( TXGdi(IDS_INVALIDDIBHANDLE) );
  52.   }
  53.   int colorAlloc;
  54.   if (IsCore) {
  55.     NumClrs = NColors(((LPBITMAPCOREINFO)Info)->bmciHeader.bcBitCount);
  56.     colorAlloc = (int)NumClrs * sizeof(RGBTRIPLE);
  57.     W = ((LPBITMAPCOREINFO)Info)->bmciHeader.bcWidth;
  58.     H = ((LPBITMAPCOREINFO)Info)->bmciHeader.bcHeight;
  59.   } else {
  60.     NumClrs = NColors(Info->bmiHeader.biBitCount);
  61.     colorAlloc = (int)NumClrs * sizeof(RGBQUAD);
  62.     W = (int)Info->bmiHeader.biWidth;
  63.     H = (int)Info->bmiHeader.biHeight;
  64.   }
  65.   Bits = (char far*)Info + ((int)Info->bmiHeader.biSize + colorAlloc);
  66.   Mode = DIB_RGB_COLORS;
  67. }
  68.  
  69. //
  70. // Construct a TDib from a borrowed handle
  71. //
  72. TDib::TDib(HGLOBAL handle, TAutoDelete autoDelete)
  73.   : TGdiBase(handle, autoDelete), Info(0), Bits(0), NumClrs(0), W(0), H(0),
  74.     IsCore(FALSE), IsResHandle(FALSE)
  75. {
  76.   InfoFromHandle();
  77. }
  78.  
  79. //
  80. // Construct a TDib borrowed from a clipboard handle
  81. //
  82. TDib::TDib(const TClipboard& clipboard)
  83.   : TGdiBase(clipboard.GetClipboardData(CF_DIB)), Info(0), Bits(0),
  84.     NumClrs(0), W(0), H(0), IsCore(FALSE), IsResHandle(FALSE)
  85. {
  86.   InfoFromHandle();
  87. }
  88.  
  89. //
  90. // Construct a TDib that is a copy of an existing one
  91. //
  92. TDib::TDib(const TDib& dib)
  93.   : Info(0), Bits(0), NumClrs(0), W(0), H(0), IsCore(FALSE), IsResHandle(FALSE)
  94. {
  95.   PRECONDITION(dib.IsOK());
  96.  
  97.   long size = ::GlobalSize(dib.Handle);
  98.   Handle = ::GlobalAlloc(GMEM_MOVEABLE, size);
  99.   if (!Handle)
  100.     THROW( TXOutOfMemory() );
  101.  
  102.   Info = (LPBITMAPINFO)::GlobalLock(Handle);
  103.   hmemcpy(Info, dib.Info, size);
  104.   IsCore = dib.IsCore;
  105.   NumClrs = dib.NumClrs;
  106.   W = dib.W;
  107.   H = dib.H;
  108.   Mode = dib.Mode;
  109.   int colorAlloc = (int)NumClrs *
  110.                    (IsCore ? sizeof(RGBTRIPLE) : sizeof(RGBQUAD));
  111.   Bits = (char far*)Info + ((int)Info->bmiHeader.biSize + colorAlloc);
  112. }
  113.  
  114.  
  115. TDib::~TDib()
  116. {
  117.   if (Handle)
  118.     if (IsResHandle) {
  119.       #if !defined(__WIN32__)
  120.         ::UnlockResource(Handle);
  121.         if (ShouldDelete)
  122.           ::FreeResource(Handle);
  123.       #endif
  124.  
  125.     } else {
  126.       ::GlobalUnlock(Handle);
  127.       if (ShouldDelete)
  128.         ::GlobalFree(Handle);
  129.     }
  130. }
  131.  
  132. //
  133. // Convert an absolute RGB color table to a palette relative color table
  134. // Makes sure that color table is RGB
  135. //
  136. BOOL
  137. TDib::ChangeModeToPal(const TPalette& pal)
  138. {
  139.   if (Mode != DIB_RGB_COLORS)
  140.     return FALSE;
  141.  
  142.   WORD nEntries = pal.GetNumEntries();
  143.   
  144.   for (int c = 0; c < NumClrs; c++) {
  145.     WORD index = WORD(c);
  146.     for (WORD i = 0; i < nEntries; i++) {
  147.       PALETTEENTRY pe; //getting all entries one time up front would be faster
  148.       pal.GetPaletteEntry(i, pe);
  149.       if (pe.peRed == Info->bmiColors[c].rgbRed &&
  150.           pe.peGreen == Info->bmiColors[c].rgbGreen &&
  151.           pe.peBlue == Info->bmiColors[c].rgbBlue) {
  152.         index = i;
  153.         break;
  154.       }
  155.     }
  156.     ((WORD*)Info->bmiColors)[c] = index;
  157.   }
  158.   Mode = DIB_PAL_COLORS;
  159.   return TRUE;
  160. }
  161.  
  162. //
  163. // Convert a palette relative color table to an absolute RGB color table
  164. // Makes sure that color table is pal relative & that there is enough space
  165. //
  166. BOOL
  167. TDib::ChangeModeToRGB(const TPalette& pal)
  168. {
  169.   if (Mode != DIB_PAL_COLORS ||
  170.       (int)((char*)Bits - (char*)Info) < NumClrs*sizeof(RGBQUAD))
  171.     return FALSE;
  172.   
  173.   WORD nEntries = pal.GetNumEntries();
  174.  
  175.   for (int c = (int)NumClrs-1; c >= 0; c--) {
  176.     WORD i = ((WORD*)Info->bmiColors)[c];
  177.     if (i >= nEntries)
  178.       i = 0;
  179.     PALETTEENTRY pe;
  180.     pal.GetPaletteEntry(i, pe);
  181.     Info->bmiColors[c].rgbRed = pe.peRed;
  182.     Info->bmiColors[c].rgbGreen = pe.peGreen;
  183.     Info->bmiColors[c].rgbBlue = pe.peBlue;
  184.   }
  185.   Mode = DIB_RGB_COLORS;
  186.   return TRUE;
  187. }
  188.  
  189. //
  190. // Get, set, find and map the color table entries as colors(RGBQUADs)
  191. //
  192. TColor
  193. TDib::GetColor(int entry) const
  194. {
  195.   if (entry >= 0 && entry < NumClrs)
  196.     if (Mode == DIB_RGB_COLORS)
  197.       return GetColors()[entry];
  198.  
  199.   return 0;
  200. }
  201.  
  202. void
  203. TDib::SetColor(int entry, TColor color)
  204. {
  205.   if (entry >= 0 && entry < NumClrs)
  206.     if (Mode == DIB_RGB_COLORS)
  207.       GetColors()[entry] = color;
  208. }
  209.  
  210. int
  211. TDib::FindColor(TColor color)
  212. {
  213.   for (int entry = 0; entry < NumClrs; entry++)
  214.     if (color == GetColors()[entry])
  215.       return entry;
  216.   return -1;
  217. }
  218.  
  219. int
  220. TDib::MapColor(TColor fromColor, TColor toColor, BOOL doAll)
  221. {
  222.   for (int entry = 0, count = 0; entry < NumClrs; entry++)
  223.     if (fromColor == GetColors()[entry]) {
  224.       GetColors()[entry] = toColor;
  225.       count++;
  226.       if (!doAll)
  227.         break;
  228.     }
  229.   return count;
  230. }
  231.  
  232. //
  233. // Get, set, find and map the color table entries as palette indices
  234. //
  235. WORD
  236. TDib::GetIndex(int entry) const
  237. {
  238.   if (entry >= 0 && entry < NumClrs)
  239.     if (Mode == DIB_PAL_COLORS)
  240.       return ((WORD*)GetColors())[entry];
  241.  
  242.   return 0;
  243. }
  244.  
  245. void
  246. TDib::SetIndex(int entry, WORD index)
  247. {
  248.   if (entry >= 0 && entry < NumClrs)
  249.     if (Mode == DIB_PAL_COLORS)
  250.       ((WORD*)GetColors())[entry] = index;
  251. }
  252.  
  253. int
  254. TDib::FindIndex(WORD index)
  255. {
  256.   for (int entry = 0; entry < NumClrs; entry++)
  257.     if (GetIndices()[entry] == index)
  258.       return entry;
  259.   return -1;
  260. }
  261.  
  262. int
  263. TDib::MapIndex(WORD fromIndex, WORD toIndex, BOOL doAll)
  264. {
  265.   for (int entry = 0, count = 0; entry < NumClrs; entry++)
  266.     if (GetIndices()[entry] == fromIndex) {
  267.       GetIndices()[entry] = toIndex;
  268.       count++;
  269.       if (!doAll)
  270.         break;
  271.     }
  272.   return count;
  273. }
  274.  
  275. void
  276. TDib::MapUIColors(UINT mapColors, TColor* bkColor)
  277. {
  278.   if (mapColors & TDib::MapText)
  279.     MapColor(TColor::Black, ::GetSysColor(COLOR_BTNTEXT));
  280.   if (mapColors & TDib::MapFace)
  281.     MapColor(TColor::LtGray, ::GetSysColor(COLOR_BTNFACE));
  282.   if (mapColors & TDib::MapFace)
  283.     MapColor(TColor::Gray, ::GetSysColor(COLOR_BTNSHADOW));
  284.   if (mapColors & TDib::MapFace)
  285.     MapColor(TColor::White, ::GetSysColor(COLOR_BTNHIGHLIGHT));
  286.   if (mapColors & TDib::MapFrame)
  287.     MapColor(TColor::LtMagenta, ::GetSysColor(COLOR_WINDOWFRAME));
  288.   if (bkColor)
  289.     MapColor(TColor::LtYellow, *bkColor);
  290. }
  291.  
  292. //
  293. // Move this dib to the clipboard. Ownership of the DIB is passed to the
  294. // clipboard.
  295. //
  296. void
  297. TDib::ToClipboard(TClipboard& clipboard)
  298. {
  299.   if (Handle) {
  300.     if (IsResHandle) {
  301.       #if !defined(__WIN32__)
  302.         ::UnlockResource(Handle);
  303.       #endif
  304.     } else {
  305.       ::GlobalUnlock(Handle);
  306.     }
  307.     clipboard.SetClipboardData(CF_DIB, Handle);
  308.     ShouldDelete = FALSE;
  309.     Info = 0;
  310.     Bits = 0;
  311.     Handle = 0;
  312.   }
  313. }
  314.  
  315. #endif  //section 1
  316. #if !defined(SECTION) || SECTION == 2
  317.  
  318. //
  319. // Construct a Dib given a .BMP file name
  320. //
  321. TDib::TDib(const char* name)
  322.   : Info(0), Bits(0), NumClrs(0), W(0), H(0), IsCore(FALSE), IsResHandle(FALSE)
  323. {
  324.   if (!LoadFile(name))
  325.     THROW( TXGdi(IDS_GDIFILEREADFAIL) );
  326. }
  327.  
  328. //
  329. // Test if the passed file is a Windows 3.0 DI(or PM 1.x) bitmap
  330. //  and if so read it.
  331. //  Report errors if unable to do so. Adjust the Scroller to the new
  332. //  bitmap dimensions.
  333. //
  334. BOOL
  335. TDib::LoadFile(const char* name)
  336. {
  337.   TFile file(name, TFile::ReadOnly);
  338.   if (!file.IsOpen()) {
  339.     TRACEX(OwlGDI, 0, "Cannot open bitmap file '" << name << "' to read");
  340.     return FALSE;
  341.   }
  342.  
  343.   // read file header and verify the signature
  344.   BITMAPFILEHEADER bmf;
  345.   if (file.Read(&bmf, sizeof(bmf)) != sizeof(bmf) || bmf.bfType != 'BM') {
  346.     TRACEX(OwlGDI, 0, "Not a Windows 3.x or OS/2 1.x bitmap file '" << name << "'");
  347.     file.Close();
  348.     return FALSE;
  349.   }
  350.  
  351.   // we ignore all other information in the file header
  352.   // since some applications do not put correct information in
  353.   // the fields...
  354.   //
  355.   if (!Read(file,bmf.bfOffBits ? bmf.bfOffBits-sizeof(BITMAPFILEHEADER) : 0)) {
  356.     file.Close();
  357.     return FALSE;
  358.   }
  359.   file.Close();
  360.   return TRUE;
  361. }
  362.  
  363.  
  364. #endif
  365. #if !defined(SECTION) || SECTION == 3
  366.  
  367. //
  368. // Construct a Dib given a module instance and a resource name or int Id
  369. //
  370. TDib::TDib(HINSTANCE instance, TResId resId)
  371.   : Info(0), Bits(0), NumClrs(0), W(0), H(0), IsCore(FALSE), IsResHandle(FALSE)
  372. {
  373.   if (!LoadResource(instance, resId))
  374.     THROW( TXGdi(IDS_GDIRESLOADFAIL) );
  375. }
  376.  
  377. //
  378. // Load a dib resource into a dib.  Either use ::LoadResource, or use
  379. // ::AccessResource get to the file handle and read it like a BMP file.
  380. //
  381. BOOL
  382. TDib::LoadResource(HINSTANCE instance, TResId resId)
  383. {
  384. #if TRUE || defined(__WIN32__)  // This version works in all cases
  385.  
  386.   // First, load the resource into a global memory block.
  387.   //
  388.   HRSRC  resHandle = ::FindResource(instance, resId, RT_BITMAP);
  389.   if (resHandle)
  390.     Handle = ::LoadResource(instance, resHandle);
  391.   else
  392.     Handle = 0;
  393.   if (!Handle) {
  394.     TRACEX(OwlGDI, 0, "Cannot access bitmap resource");
  395.     return FALSE;
  396.   }
  397.   IsResHandle = TRUE;
  398.  
  399.   // Then update our pointers & other info.
  400.   //
  401.   InfoFromHandle();
  402.  
  403.   // Under Win32, resources are read-only. So, to allow for later modification
  404.   // of the Dib, a copy must be made. Could postpone this until dib needed
  405.   // to be written on...
  406.   //
  407.   #if defined(__WIN32__)
  408.     long size = ::SizeofResource(instance, resHandle);
  409.     HANDLE tempHandle = ::GlobalAlloc(GMEM_MOVEABLE, size);
  410.     if (!tempHandle)
  411.       THROW( TXOutOfMemory() );
  412.  
  413.     void* tempInfo = ::GlobalLock(tempHandle);
  414.     hmemcpy(tempInfo, Info, size);
  415.  
  416.     // Handle will now be a memory handle, & no longer a res handle
  417.     // Update Bits pointer & other members that may have moved.
  418.     //
  419.     Handle = tempHandle;
  420.     Info = (LPBITMAPINFO)tempInfo;
  421.     IsResHandle = FALSE;
  422.     InfoFromHandle();
  423.   #endif
  424.  
  425.   return TRUE;
  426.  
  427. #else   // This version will work for win16
  428.  
  429.   // We use the low-level resource functions here so that
  430.   // the same routines can be used to read DIB's from files
  431.   // and resources
  432.   //
  433.   TFile  file(::AccessResource(instance, ::FindResource(instance, resId, RT_BITMAP)));
  434.   if (!file.IsOpen()) {
  435.     TRACEX(OwlGDI, 0, "Cannot access bitmap resource");
  436.     return FALSE;
  437.   }
  438.   // a bitmap resource is just like a bitmap file without
  439.   // the BITMAPFILEHEADER structure
  440.   //
  441.   if (!Read(file)) {
  442.     file.Close();
  443.     return FALSE;
  444.   }
  445.   file.Close();
  446.   return TRUE;
  447.  
  448. #endif
  449. }
  450.  
  451. //
  452. // Read a Windows 3.0 or PM 1.X device independent bitmap. (.BMP)
  453. //  Check header, read Info, palette and bitmap.  PM Dibs can be converted to
  454. //  Win 3.0 Dibs on the fly.
  455. // Return true iff Dib was read OK
  456. //
  457. BOOL
  458. TDib::Read(TFile& file, long offBits)
  459. {
  460.   DWORD headerSize;
  461.   if (file.Read(&headerSize, sizeof(headerSize)) != sizeof(headerSize)
  462.     || headerSize != sizeof(BITMAPCOREHEADER)
  463.     && headerSize != sizeof(BITMAPINFOHEADER)) {
  464.     TRACEX(OwlGDI, 0, "Not a Windows 3.x or PM 1.x bitmap file");
  465.     return FALSE;
  466.   }
  467.  
  468.   // Prepare to accept a header that is either Core(PM) or Info(Win) type
  469.   // Note thet the biSize and the bcSize fields are the same(the only ones).
  470.   //
  471.   union {
  472.     BITMAPINFOHEADER infoHeader;
  473.     BITMAPCOREHEADER coreHeader;
  474.   };
  475.   #if defined(CVT_CORE_TO_INFO)
  476.     infoHeader.biSize = sizeof(BITMAPINFOHEADER);
  477.   #else
  478.     infoHeader.biSize = headerSize;
  479.   #endif
  480.   if (file.Read(&infoHeader.biWidth, (int)headerSize-sizeof(DWORD)) !=
  481.       (int)headerSize-sizeof(DWORD)) {
  482.     TRACEX(OwlGDI, 0, "Invalid DIB Header");
  483.     return FALSE;
  484.   }
  485.  
  486.   // Type dependent fields kept independently
  487.   //
  488.   WORD  bitCount;
  489.   int   colorAlloc;
  490.   int   colorRead;
  491.   DWORD bitsAlloc;
  492.  
  493.   // If this is a PM 1.X Dib, expand header and fill out reamining fields
  494.   // for win3 dib info
  495.   // Calculate size of color table in memory using RGBQUADs if converting.
  496.   // For PM Dibs, this is NOT the size on disk.
  497.   //
  498.   if (headerSize == sizeof(BITMAPCOREHEADER)) {
  499.     // check number of planes. Windows 3.x supports only 1 plane DIBs
  500.     if (coreHeader.bcPlanes != 1) {
  501.       TRACEX(OwlGDI, 0, "Invalid number of planes in PM 1.X bitmap");
  502.       return FALSE;
  503.     }
  504.     bitCount = coreHeader.bcBitCount;
  505.     NumClrs = NColors(bitCount);
  506.     colorRead = (int)NumClrs * sizeof(RGBTRIPLE); // Color tables on disk
  507.     W = coreHeader.bcWidth;
  508.     H = coreHeader.bcHeight;
  509.     #if defined(CVT_CORE_TO_INFO)
  510.       IsCore = FALSE;
  511.       // Note reverse field order for copying in place
  512.       infoHeader.biBitCount = coreHeader.bcBitCount;
  513.       infoHeader.biPlanes = 1;
  514.       infoHeader.biWidth = W;
  515.       infoHeader.biHeight = H;
  516.       infoHeader.biCompression = BI_RGB;
  517.       infoHeader.biSizeImage = 0; // calculate this below
  518.       infoHeader.biXPelsPerMeter = 0;
  519.       infoHeader.biYPelsPerMeter = 0;
  520.       infoHeader.biClrUsed = NumClrs;
  521.       infoHeader.biClrImportant = 0;
  522.       colorAlloc = NumClrs * sizeof(RGBQUAD); // size of color tables in mem
  523.     #else
  524.       IsCore = TRUE;
  525.       colorAlloc = colorRead;
  526.     #endif
  527.     bitsAlloc = 0;      // Calculate below
  528.   } else {
  529.     // check number of planes. Windows 3.x supports only 1 plane DIBs
  530.     if (infoHeader.biPlanes != 1) {
  531.       TRACEX(OwlGDI, 0, "Invalid number of planes in Win 3.X bitmap");
  532.       return FALSE;
  533.     }
  534.     IsCore = FALSE;
  535.     bitCount = infoHeader.biBitCount;
  536.     if (!infoHeader.biClrUsed)
  537.       infoHeader.biClrUsed = NColors(bitCount);
  538.     NumClrs = (int)infoHeader.biClrUsed;
  539.     colorAlloc = (int)NumClrs * sizeof(RGBQUAD); // size of color tables
  540.     colorRead = colorAlloc;
  541.     W = (int)infoHeader.biWidth;
  542.     H = (int)infoHeader.biHeight;
  543.     bitsAlloc = infoHeader.biSizeImage;
  544.   }
  545.  
  546.   // Some applications do not fill in the SizeImage field in the header.
  547.   // (Actually the truth is more likely that some drivers do not fill the
  548.   // field in and the apps do not compensate for these buggy drivers.)
  549.   // Or it is a PM 1.X Dib.
  550.   // Therefore, if compression was not used, we will(re)compute the size,
  551.   // but if compression is used, we have no choice but to trust the size.
  552.   //
  553.   if (IsCore || infoHeader.biCompression == BI_RGB) {
  554.     bitsAlloc = ScanBytes(W, bitCount) * H;
  555.     if (!IsCore)
  556.       infoHeader.biSizeImage = bitsAlloc;
  557.   }
  558.  
  559.   Handle = ::GlobalAlloc(GMEM_MOVEABLE, infoHeader.biSize + colorAlloc + bitsAlloc);
  560.   if (!Handle)
  561.     THROW( TXOutOfMemory() );
  562.  
  563.   Info = (LPBITMAPINFO)::GlobalLock(Handle);
  564.   Info->bmiHeader = infoHeader;
  565.  
  566.   // Read color table.  Expand to RGBQUADs if it is a PM Dib & we are converting
  567.   //
  568.   if (colorAlloc) {
  569.     if (file.Read((char far*)Info+(int)infoHeader.biSize, colorRead) != colorRead) {
  570.       TRACEX(OwlGDI, 0, "Could not read color table");
  571.       ::GlobalUnlock(Handle);
  572.       return FALSE;
  573.     }
  574.     #if defined(CVT_CORE_TO_INFO)
  575.     if (IsCore) {
  576.       for (int i = NumClrs-1; i >= 0; i--) {
  577.         Info->bmiColors[i].rgbRed = ((RGBTRIPLE*)Info->bmiColors)[i].rgbtRed;
  578.         Info->bmiColors[i].rgbGreen = ((RGBTRIPLE*)Info->bmiColors)[i].rgbtGreen;
  579.         Info->bmiColors[i].rgbBlue = ((RGBTRIPLE*)Info->bmiColors)[i].rgbtBlue;
  580.         Info->bmiColors[i].rgbReserved = 0;
  581.       }
  582.     }
  583.     #endif
  584.   }
  585.   Mode = DIB_RGB_COLORS;
  586.  
  587.   // Locate & Read Bits, skipping Pad if any.  Ignore OffBits if it is zero.
  588.   // Ignore OffBits if less than the current position(its probably bad)
  589.   //
  590.   Bits = (char far*)Info +((int)infoHeader.biSize + colorAlloc);
  591.   if (offBits && offBits - (long)(headerSize+colorRead) > 0)
  592.     file.Seek(offBits- (headerSize+colorRead), TFile::cur);
  593.   if (file.Read(Bits, bitsAlloc) != bitsAlloc) {
  594.     TRACEX(OwlGDI, 0, "Could not read DIB bits");
  595.     return FALSE;
  596.   }
  597.   return TRUE;
  598. }
  599.  
  600. #endif //section 3
  601. #if !defined(SECTION) || SECTION == 4
  602.  
  603. BOOL
  604. TDib::WriteFile(const char* name)
  605. {
  606.   TFile file(name, TFile::WriteOnly|TFile::Create|TFile::DenyRdWr, TFile::PermRdWr);
  607.  
  608.   if (!file.IsOpen()) {
  609.     TRACEX(OwlGDI, 0, "Cannot open bitmap file '" << name << "' to write");
  610.     return FALSE;
  611.   }
  612.  
  613.   long size = ::GlobalSize(Handle);
  614.  
  615.   // write file header
  616.   BITMAPFILEHEADER bmf;
  617.   bmf.bfType = 'BM';
  618.   bmf.bfSize = sizeof(bmf) + size;
  619.   bmf.bfReserved1 = 0;
  620.   bmf.bfReserved2 = 0;
  621.   bmf.bfOffBits = sizeof(bmf) +(char far*)Bits - (char far*)Info;
  622.   if (file.Write(&bmf, sizeof(bmf)) != sizeof(bmf) ||
  623.       file.Write((void HUGE*)Info, size) != size) {
  624.     TRACEX(OwlGDI, 0, "Disk error writing file '" << name << "'");
  625.     file.Close();
  626.     return FALSE;
  627.   }
  628.   file.Close();
  629.   return TRUE;
  630. }
  631.  
  632. #endif //section 4
  633. #if !defined(SECTION) || SECTION == 5
  634.  
  635. //
  636. // Construct a Dib given dimensions and color depth
  637. //
  638. TDib::TDib(int width, int height, int nColors, WORD mode)
  639.   : Info(0), Bits(0), NumClrs(0), W(0), H(0), IsCore(FALSE), IsResHandle(FALSE)
  640. {
  641.   PRECONDITION(width && height && nColors);
  642.  
  643.   BITMAPINFOHEADER      InfoHeader;
  644.   InfoHeader.biSize       = sizeof(BITMAPINFOHEADER);
  645.   InfoHeader.biWidth      = width;
  646.   InfoHeader.biHeight     = height;
  647.   InfoHeader.biBitCount   = NBits(nColors);
  648.   InfoHeader.biPlanes     = 1;
  649.   InfoHeader.biXPelsPerMeter = 0;
  650.   InfoHeader.biYPelsPerMeter = 0;
  651.   InfoHeader.biClrUsed       = nColors;
  652.   InfoHeader.biClrImportant  = 0;  // nColors;
  653.   InfoHeader.biCompression   = BI_RGB;
  654.   InfoHeader.biSizeImage = ScanBytes(width, InfoHeader.biBitCount) * height;
  655.  
  656.   int  colorAlloc = nColors * sizeof(RGBQUAD); // size of color tables
  657.   long bitsAlloc = InfoHeader.biSize + colorAlloc + InfoHeader.biSizeImage;
  658.  
  659.   Handle = ::GlobalAlloc(GMEM_MOVEABLE, bitsAlloc);
  660.   if (!Handle)
  661.     THROW( TXOutOfMemory() );
  662.  
  663.   Info = (LPBITMAPINFO)::GlobalLock(Handle);
  664.   Info->bmiHeader = InfoHeader;
  665.   InfoFromHandle();
  666.  
  667.   Mode = mode;
  668.   if (Mode == DIB_PAL_COLORS) {
  669.     // Generate a 1:1 palette relative color table- it can later be translated
  670.     // to RGB given a palette.
  671.     //
  672.     for (WORD i = 0; i < nColors; i++)
  673.      ((WORD*)Info->bmiColors)[i] = i;
  674.  
  675.   } else {
  676.   
  677.     // Get the system palette and convert to RGB quad format.
  678.     //
  679.     TScreenDC dc;
  680.     ::GetSystemPaletteEntries(dc, 0, nColors, (LPPALETTEENTRY)Info->bmiColors);
  681.     for (int i = 0; i < nColors; i++) {
  682.       Swap(Info->bmiColors[i].rgbRed, Info->bmiColors[i].rgbBlue);
  683.       Info->bmiColors[i].rgbReserved = 0;
  684.     }
  685.   }
  686. }
  687. #endif //Section 5
  688. #if !defined(SECTION) || SECTION == 6
  689.  
  690. //
  691. // Construct a TDib given a TBitmap and a TPalette
  692. // If no palette is give, uses the one in the focus window.
  693. //
  694. TDib::TDib(const TBitmap& bitmap, const TPalette* palette)
  695.   : Info(0), Bits(0), NumClrs(0), W(0), H(0), IsCore(FALSE), IsResHandle(FALSE)
  696. {
  697.   BITMAP  bm;
  698.   bitmap.GetObject(bm);
  699.  
  700.   WORD              bitCount;
  701.   BITMAPINFOHEADER  infoHeader;
  702.  
  703.   IsCore = FALSE;
  704.   infoHeader.biSize       = sizeof(BITMAPINFOHEADER);
  705.   infoHeader.biWidth      = W = bm.bmWidth;
  706.   infoHeader.biHeight     = H = bm.bmHeight;
  707.   if (palette) {
  708.     WORD nColors;
  709.     palette->GetObject(nColors);
  710.     infoHeader.biBitCount    = bitCount = NBits(nColors);
  711.   } else
  712.     infoHeader.biBitCount    = bitCount = WORD(bm.bmBitsPixel*bm.bmPlanes);
  713.   infoHeader.biPlanes        = 1;
  714.   infoHeader.biXPelsPerMeter = 0;
  715.   infoHeader.biYPelsPerMeter = 0;
  716.   infoHeader.biClrUsed       = NumClrs = NColors(bitCount);
  717.   infoHeader.biClrImportant  = 0;
  718.   infoHeader.biCompression   = BI_RGB;
  719.   infoHeader.biSizeImage     = ScanBytes(W, bitCount) * H;
  720.  
  721.   int  colorAlloc = (int)NumClrs * sizeof(RGBQUAD); // size of color tables
  722.   long bitsAlloc = infoHeader.biSize + colorAlloc + infoHeader.biSizeImage;
  723.  
  724.   Handle = ::GlobalAlloc(GMEM_MOVEABLE, bitsAlloc);
  725.   if (!Handle)
  726.     THROW( TXOutOfMemory() );
  727.  
  728.   Info = (LPBITMAPINFO)::GlobalLock(Handle);
  729.   Info->bmiHeader = infoHeader;
  730.  
  731.   TScreenDC dc;
  732.   if (palette)
  733.     dc.SelectObject(*palette, FALSE);
  734.   Bits = (char far*)Info + ((int)infoHeader.biSize + colorAlloc);
  735.   Mode = DIB_RGB_COLORS;
  736.   dc.GetDIBits(bitmap, StartScan(), NumScans(), Bits, *Info, Usage());
  737. }
  738.  
  739. #endif //Section 6
  740.