home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / cxdc1.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  72.7 KB  |  2,252 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20.  
  21. #include "cxdc.h"
  22. #include "cntritem.h"
  23. #include "intlwin.h"
  24. #include "mainfrm.h"
  25. #include "npapi.h"
  26. #include "np.h"
  27. #include "feembed.h"
  28. #include "fmabstra.h"
  29. #include "custom.h"
  30. #include "prefapi.h"
  31. #include "feimage.h"
  32. #include "il_icons.h"
  33. #include "prefinfo.h"
  34.  
  35. //    Make an array of RGB colors that match the current palette.
  36. //  This array is used for contexts that don't employ DibPalColors.
  37. //  Returns TRUE on success, FALSE otherwise.
  38. static const    RGBQUAD rgbqWhite = {0xFF, 0xFF, 0xFF, 0};
  39. static const    RGBQUAD rgbqBlack = {0, 0, 0, 0};
  40.  
  41. //#define USE_IDENTITY_PALETTE
  42. #ifdef XP_WIN32
  43. //#define USE_DIB_SECTION
  44. #endif
  45. #ifdef USE_IDENTITY_PALETTE
  46. #    define PALETTEENTRY_FLAGS   PC_NOCOLLAPSE
  47. #else
  48. #    define PALETTEENTRY_FLAGS   0
  49. #endif
  50. extern "C"{
  51. extern int gifAbort;
  52. }
  53.  
  54. #define ROP_PSDPxax    0x00B8074AL
  55. // Alters the transparent part of the source image (already selected into
  56. // pSrcDC) with the specified brush
  57. //
  58. // Make sure that the WHOLE image is changed and not just the part that
  59. // needs to be displayed; otherwise things will get out of sync
  60.  
  61. static BOOL
  62. CopyPaletteToRGBArray(HPALETTE pPal, RGBQUAD *pRGBArray) 
  63. {
  64.     PALETTEENTRY *paletteEntries;
  65.     XP_ASSERT(pRGBArray);
  66.  
  67.     paletteEntries = (PALETTEENTRY *)XP_ALLOC(sizeof(PALETTEENTRY) * 256);
  68.     
  69.     if (!paletteEntries)
  70.         return FALSE;
  71.  
  72.     // Copy existing palette
  73.     VERIFY(::GetPaletteEntries(pPal, 0, 256, paletteEntries) > 0);
  74.     
  75.     for(int i = 0; i < 256; i++)    {
  76.         pRGBArray[i].rgbRed   = paletteEntries[i].peRed;
  77.         pRGBArray[i].rgbGreen = paletteEntries[i].peGreen;
  78.         pRGBArray[i].rgbBlue  = paletteEntries[i].peBlue;
  79.         pRGBArray[i].rgbReserved = NULL;
  80.     }
  81.  
  82.     XP_FREE(paletteEntries);
  83.     return TRUE;
  84. }
  85.  
  86.  
  87.  
  88. void CDCCX::ImageComplete(NI_Pixmap* image)
  89. {
  90.     FEBitmapInfo *imageInfo;
  91.     HDC hdc = GetContextDC();
  92.     if (!image || !hdc || IsPrintContext()) return;
  93.  
  94.     imageInfo = (FEBitmapInfo*) image->client_data;
  95.     if(!imageInfo)
  96.         return;
  97.  
  98. #ifndef USE_DIB_SECTION
  99.     if(!imageInfo->hBitmap) {
  100.         // Attempt to create a bitmap
  101.         if (!imageInfo->IsMask ) {
  102.             imageInfo->hBitmap = ::CreateDIBitmap(hdc,
  103.                                    &(imageInfo->bmpInfo->bmiHeader),
  104.                                    CBM_INIT, 
  105.                                    image->bits, 
  106.                                    imageInfo->bmpInfo, 
  107.                                    m_bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS);
  108.             if (imageInfo->hBitmap) {
  109.                 // Free the image bits since we no longer need them
  110.                 CDCCX::HugeFree(image->bits);
  111.                 image->bits = NULL;
  112.             }
  113.         }
  114.         else {
  115.             // If there is a mask then create another bitmap
  116.             // Build a BITMAPINFO struct for mask
  117.             char          cMask[sizeof(BITMAPINFOHEADER) + (2 * sizeof(RGBQUAD))];
  118.             LPBITMAPINFO pBmInfoMask = (LPBITMAPINFO)cMask;
  119.         
  120.             memcpy(pBmInfoMask, imageInfo->bmpInfo, sizeof(BITMAPINFOHEADER));
  121.             pBmInfoMask->bmiHeader.biBitCount = 1;
  122.             pBmInfoMask->bmiHeader.biCompression = BI_RGB;  // must NOT be BI_BITFIELDS
  123.         
  124.             // Build a color table for monochrome mask. Image lib sets the foreground
  125.             // pixels to 1 and the background pixels to 0. We want the monochrome
  126.             // mask to be the same way
  127.             pBmInfoMask->bmiColors[1] = rgbqBlack;  // background pixels
  128.             pBmInfoMask->bmiColors[0] = rgbqWhite;  // foreground pixels
  129.             // Create the mask. It's important that we use the memory DC, because we
  130.             // want a momochrome bitmap
  131.             imageInfo->hBitmap = ::CreateDIBitmap(m_pImageDC,
  132.                 (LPBITMAPINFOHEADER)pBmInfoMask,
  133.                 CBM_INIT,
  134.                 image->bits,
  135.                 pBmInfoMask,
  136.                 DIB_RGB_COLORS);
  137.  
  138.             if (imageInfo->hBitmap) {
  139.                 // Free the mask bits since we no longer need them
  140.                 CDCCX::HugeFree(image->bits);
  141.                 image->bits = NULL;
  142.             }
  143.         }
  144.     }
  145. #else
  146.     HBITMAP oldBmp;
  147.     oldBmp = imageInfo->hBitmap;
  148.  
  149.     if (!imageInfo->IsMask ) {
  150.         imageInfo->hBitmap = ::CreateDIBitmap(hdc,
  151.                                &(imageInfo->bmpInfo->bmiHeader),
  152.                                CBM_INIT, 
  153.                                image->bits, 
  154.                                imageInfo->bmpInfo, 
  155.                                m_bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS);
  156.     }
  157.     else {
  158.         // If there is a mask then create another bitmap
  159.         // Build a BITMAPINFO struct for mask
  160.         char          cMask[sizeof(BITMAPINFOHEADER) + (2 * sizeof(RGBQUAD))];
  161.         LPBITMAPINFO pBmInfoMask = (LPBITMAPINFO)cMask;
  162.     
  163.         memcpy(pBmInfoMask, imageInfo->bmpInfo, sizeof(BITMAPINFOHEADER));
  164.         pBmInfoMask->bmiHeader.biBitCount = 1;
  165.         pBmInfoMask->bmiHeader.biCompression = BI_RGB;  // must NOT be BI_BITFIELDS
  166.     
  167.         // Build a color table for monochrome mask. Image lib sets the foreground
  168.         // pixels to 1 and the background pixels to 0. We want the monochrome
  169.         // mask to be the same way
  170.         pBmInfoMask->bmiColors[1] = rgbqBlack;  // background pixels
  171.         pBmInfoMask->bmiColors[0] = rgbqWhite;  // foreground pixels
  172.         // Create the mask. It's important that we use the memory DC, because we
  173.         // want a momochrome bitmap
  174.         imageInfo->hBitmap = ::CreateDIBitmap(m_pImageDC,
  175.             (LPBITMAPINFOHEADER)pBmInfoMask,
  176.             CBM_INIT,
  177.             image->bits,
  178.             pBmInfoMask,
  179.             DIB_RGB_COLORS);
  180.  
  181.     }
  182.     ::DeleteObject(oldBmp);
  183.     image->bits = NULL;
  184. #endif
  185.     ReleaseContextDC(hdc);
  186. }
  187.  
  188. static WORD
  189. GetBitCount(BITMAP &bmp)
  190. {
  191.     WORD    nBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
  192.  
  193. #ifdef XP_WIN32
  194.     if (nBits == 1) 
  195.         nBits = 1; 
  196.     else if (nBits <= 4) 
  197.         nBits = 4; 
  198.     else if (nBits <= 8) 
  199.         nBits = 8; 
  200.     else if (nBits <= 16) 
  201.         nBits = 16; 
  202.     else if (nBits <= 24) 
  203.         nBits = 24; 
  204.     else 
  205.         nBits = 32;
  206. #else
  207.     if (nBits == 1) 
  208.         nBits = 1; 
  209.     else if (nBits <= 4) 
  210.         nBits = 4; 
  211.     else if (nBits <= 8) 
  212.         nBits = 8; 
  213.     else
  214.         nBits = 24; 
  215. #endif
  216.  
  217.     return nBits;
  218. }
  219.  
  220. #ifndef XP_WIN32
  221. /* Quaternary raster codes */
  222. #define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore))
  223. #endif
  224.  
  225. BOOL CDCCX::CanWriteBitmapFile(LO_ImageStruct* pLOImage)
  226. {
  227.     ASSERT(pLOImage);
  228.     if(!pLOImage)  {
  229.         return(FALSE);
  230.     }
  231.     IL_Pixmap *pImage = IL_GetImagePixmap(pLOImage->image_req);
  232.  
  233.     //  Internal icons have no platform data.
  234.     FEBitmapInfo* imageinfo = (FEBitmapInfo*) pImage->client_data;
  235.  
  236.     // We can't do anything if we don't have all the image bits
  237.     return imageinfo && imageinfo->hBitmap;
  238. }
  239.  
  240. HANDLE CDCCX::WriteBitmapToMemory(    IL_ImageReq *image_req, LO_Color* bg)
  241. {
  242.     IL_Pixmap *pImage = IL_GetImagePixmap(image_req);
  243.     IL_Pixmap *pMask = IL_GetMaskPixmap(image_req);
  244.  
  245.     // Windows bitmap file format looks like this:
  246.     //
  247.     // +------------------+
  248.     // | BITMAPFILEHEADER |
  249.     // |------------------|
  250.     // | BITMAPINFOHEADER |
  251.     // |------------------|
  252.     // | color table      |
  253.     // |------------------|
  254.     // | image bits       |
  255.     // +------------------+
  256.     FEBitmapInfo* imageinfo = (FEBitmapInfo*) pImage->client_data;
  257.  
  258.     FEBitmapInfo* maskinfo = 0;
  259.     if (pMask)
  260.         maskinfo = (FEBitmapInfo*) pMask->client_data;
  261.  
  262.     // We can't do anything if we don't have all the image bits
  263.     HGLOBAL hDib;
  264.     if (imageinfo && imageinfo->hBitmap) {
  265.         BITMAP                bmp;
  266.         LPBITMAPINFOHEADER    lpBmi;
  267.         WORD                nBitCount;
  268.         LPBYTE                lpBits;
  269.         int                    nColorTable;
  270.  
  271.         // Determine the bits per pixel
  272.         if (!::GetObject(imageinfo->hBitmap, sizeof(bmp), &bmp))
  273.             return FALSE;
  274.  
  275.         nBitCount = GetBitCount(bmp);
  276.  
  277.         // We need to know how big the color table is. For 16-bit mode and 32-bit mode, we need to
  278.         // allocate room for 3 double-word color masks
  279.         if (nBitCount == 16 || nBitCount == 32)
  280.             nColorTable = 3;
  281.         else if (nBitCount < 16)
  282.             nColorTable = 1 << nBitCount;
  283.         else {
  284.             ASSERT(nBitCount == 24);
  285.             nColorTable = 0;
  286.         }
  287.  
  288.         // Allocate space for a BITMAPINFO structure (BITMAPINFOHEADER structure
  289.         // plus space for the color table)
  290.         WORD dwSize = sizeof(BITMAPINFOHEADER) + nColorTable * sizeof(RGBQUAD);
  291.         hDib = GlobalAlloc(GMEM_SHARE, dwSize);
  292.         lpBmi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  293.         if (!lpBmi)
  294.             return FALSE;
  295.  
  296.         // Initialize the BITMAPINFOHEADER structure
  297.         lpBmi->biSize = sizeof(BITMAPINFOHEADER);
  298.         lpBmi->biWidth = bmp.bmWidth;
  299.         lpBmi->biHeight = bmp.bmHeight;
  300.         lpBmi->biPlanes = 1;
  301.         lpBmi->biBitCount = nBitCount;
  302.  
  303.         HDC    hdc = GetContextDC();
  304.  
  305.         // Note: NT 16-bit video mode won't work unless you use BI_BITFIELDS, and
  306.         // Win 95 probably won't work if you use BI_BITFIELDS. Win 3.x doesn't even
  307.         // support 16-bit DIBs, so it isn't an issue there
  308.     #ifdef XP_WIN32
  309.         if (sysInfo.m_bWinNT && (nBitCount == 16 || nBitCount == 32))
  310.             lpBmi->biCompression = BI_BITFIELDS;
  311.         else
  312.             lpBmi->biCompression = BI_RGB;
  313.     #else
  314.         lpBmi->biCompression = BI_RGB;
  315.     #endif
  316.  
  317.         // Ask the driver to tell us the number of bits we need to allocate
  318.         ::GetDIBits(hdc, imageinfo->hBitmap, 0, (int)lpBmi->biHeight, NULL, (LPBITMAPINFO)lpBmi, DIB_RGB_COLORS);
  319.  
  320.         if (lpBmi->biSizeImage == 0) {
  321.             // The driver didn't tell us so we need to compute it ourselves
  322.             lpBmi->biSizeImage = ((((lpBmi->biWidth * nBitCount) + 31) & ~31) >> 3) * lpBmi->biHeight;
  323.         }
  324.  
  325.         GlobalUnlock(hDib);
  326.         hDib = GlobalReAlloc(hDib, lpBmi->biSizeImage + dwSize,0);
  327.         // Allocate space for the bits
  328.          lpBits = (LPBYTE)GlobalLock(hDib);
  329.         if (!lpBits) {
  330.             free(lpBmi);
  331.             ReleaseContextDC(hdc);
  332.             return FALSE;
  333.         }
  334.  
  335.         // Windows bitmap files don't allow for a mask. Therefore we have to set the transparent
  336.         // parts of the image to be the appropriate color. This ensures that the bitmap file matches
  337.         // what the user sees on the screen
  338.         //
  339.         // ZZZ: This code should be shared with the code in _StretchBlt()
  340.         COLORREF    bgColor = bg ? RGB(bg->red, bg->green, bg->blue) : m_rgbBackgroundColor;
  341.  
  342.         if (maskinfo && maskinfo->hBitmap) {
  343.             HBRUSH    hBrush;
  344.             HDC tempDC = ::CreateCompatibleDC(hdc);
  345.             HBITMAP tempBmp = ::CreateCompatibleBitmap(hdc, lpBmi->biWidth, lpBmi->biHeight);
  346.             HBITMAP    hOldBmp = (HBITMAP)::SelectObject(tempDC, tempBmp);
  347.             HBITMAP    hOldBmp1 = (HBITMAP)::SelectObject(m_pImageDC, imageinfo->hBitmap);
  348.         
  349.             if (m_iBitsPerPixel == 16)
  350.                 // We don't want a dithered brush
  351.                 hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, bgColor));
  352.             else
  353.                 hBrush = ::CreateSolidBrush(0x02000000L | bgColor);
  354.  
  355.             ::BitBlt(tempDC, 0, 0,lpBmi->biWidth, lpBmi->biHeight, m_pImageDC, 0, 0, SRCCOPY);
  356.  
  357.                 // Select the mask into the memory DC
  358.             ::SelectObject(m_pImageDC, maskinfo->hBitmap);
  359.  
  360.             // Change the transparent bits of the source bitmap to the desired background
  361.             // color by doing an AND raster op
  362.             //
  363.             // The mask is monochrome and will be converted to color to match the depth of
  364.             // the destination. The foreground pixels in the mask are set to 1, and the
  365.             // background pixels to 0. When converting to a color bitmap, white pixels (1)
  366.             // are set to the background color of the DC, and black pixels (0) are set to
  367.             // the text color of the DC
  368.             //
  369.             // Select the brush
  370.             HBRUSH    hOldBrush = (HBRUSH)::SelectObject(tempDC, hBrush);
  371.  
  372.             // Draw the brush where the mask is 0
  373.             ::BitBlt(tempDC,
  374.                            0,
  375.                            0,
  376.                            lpBmi->biWidth,
  377.                            lpBmi->biHeight,
  378.                            m_pImageDC,
  379.                            0,
  380.                            0,
  381.                            MAKEROP4(SRCPAINT, R2_COPYPEN));
  382.  
  383.             ::SelectObject(tempDC, hOldBrush);
  384.  
  385.             ::DeleteObject(hBrush);
  386.             ::GetDIBits(tempDC, tempBmp, 0, (int)lpBmi->biHeight, lpBits + dwSize, (LPBITMAPINFO)lpBmi, DIB_RGB_COLORS);
  387.             ::SelectObject(m_pImageDC, hOldBmp1);
  388.             ::SelectObject(tempDC, hOldBmp);
  389.             ::DeleteObject(tempBmp);
  390.             ::DeleteDC(tempDC);
  391.         }
  392.         else
  393.         // This time have the driver give us the color table and the bits
  394.         ::GetDIBits(hdc, imageinfo->hBitmap, 0, (int)lpBmi->biHeight, lpBits + dwSize, (LPBITMAPINFO)lpBmi, DIB_RGB_COLORS);
  395.         ReleaseContextDC(hdc);
  396.         GlobalUnlock(hDib);
  397.         return (hDib);
  398.  
  399.     }
  400.     return (0);
  401. }
  402.  
  403.  
  404. BOOL CDCCX::WriteBitmapFile(LPCSTR lpszFileName, LO_ImageStruct* pLOImage)
  405. {
  406.     ASSERT(pLOImage);
  407.  
  408.     if(!pLOImage)  {
  409.         return(FALSE);
  410.     }
  411.     IL_Pixmap *pImage = IL_GetImagePixmap(pLOImage->image_req);
  412.     IL_Pixmap *pMask = IL_GetMaskPixmap(pLOImage->image_req);
  413.  
  414.     // Windows bitmap file format looks like this:
  415.     //
  416.     // +------------------+
  417.     // | BITMAPFILEHEADER |
  418.     // |------------------|
  419.     // | BITMAPINFOHEADER |
  420.     // |------------------|
  421.     // | color table      |
  422.     // |------------------|
  423.     // | image bits       |
  424.     // +------------------+
  425.     FEBitmapInfo* imageinfo = (FEBitmapInfo*) pImage->client_data;
  426.  
  427.     FEBitmapInfo* maskinfo = 0;
  428.     if (pMask)
  429.         maskinfo = (FEBitmapInfo*) pMask->client_data;
  430.  
  431.     // We can't do anything if we don't have all the image bits
  432.     if (imageinfo && imageinfo->hBitmap) {
  433.         BITMAP                bmp;
  434.         LPBITMAPINFOHEADER    lpBmi;
  435.         WORD                nBitCount;
  436.         LPBYTE                lpBits;
  437.         int                    nColorTable;
  438.  
  439.         // Determine the bits per pixel
  440.         if (!::GetObject(imageinfo->hBitmap, sizeof(bmp), &bmp))
  441.             return FALSE;
  442.  
  443.         nBitCount = GetBitCount(bmp);
  444.  
  445.         // We need to know how big the color table is. For 16-bit mode and 32-bit mode, we need to
  446.         // allocate room for 3 double-word color masks
  447.         if (nBitCount == 16 || nBitCount == 32)
  448.             nColorTable = 3;
  449.         else if (nBitCount < 16)
  450.             nColorTable = 1 << nBitCount;
  451.         else {
  452.             ASSERT(nBitCount == 24);
  453.             nColorTable = 0;
  454.         }
  455.  
  456.         // Allocate space for a BITMAPINFO structure (BITMAPINFOHEADER structure
  457.         // plus space for the color table)
  458.         lpBmi = (LPBITMAPINFOHEADER)calloc(sizeof(BITMAPINFOHEADER) + nColorTable * sizeof(RGBQUAD), 1);
  459.  
  460.         if (!lpBmi)
  461.             return FALSE;
  462.  
  463.         // Initialize the BITMAPINFOHEADER structure
  464.         lpBmi->biSize = sizeof(BITMAPINFOHEADER);
  465.         lpBmi->biWidth = bmp.bmWidth;
  466.         lpBmi->biHeight = bmp.bmHeight;
  467.         lpBmi->biPlanes = 1;
  468.         lpBmi->biBitCount = nBitCount;
  469.  
  470.         HDC    hdc = GetContextDC();
  471.  
  472.         // Note: NT 16-bit video mode won't work unless you use BI_BITFIELDS, and
  473.         // Win 95 probably won't work if you use BI_BITFIELDS. Win 3.x doesn't even
  474.         // support 16-bit DIBs, so it isn't an issue there
  475. #ifdef XP_WIN32
  476.         if (sysInfo.m_bWinNT && (nBitCount == 16 || nBitCount == 32))
  477.             lpBmi->biCompression = BI_BITFIELDS;
  478.         else
  479.             lpBmi->biCompression = BI_RGB;
  480. #else
  481.         lpBmi->biCompression = BI_RGB;
  482. #endif
  483.  
  484.         // Ask the driver to tell us the number of bits we need to allocate
  485.         ::GetDIBits(hdc, imageinfo->hBitmap, 0, (int)lpBmi->biHeight, NULL, (LPBITMAPINFO)lpBmi, DIB_RGB_COLORS);
  486.  
  487.         if (lpBmi->biSizeImage == 0) {
  488.             // The driver didn't tell us so we need to compute it ourselves
  489.             lpBmi->biSizeImage = ((((lpBmi->biWidth * nBitCount) + 31) & ~31) >> 3) * lpBmi->biHeight;
  490.         }
  491.  
  492.         // Allocate space for the bits
  493.         lpBits = (LPBYTE)HugeAlloc(lpBmi->biSizeImage, 1);
  494.  
  495.         if (!lpBits) {
  496.             free(lpBmi);
  497.             ReleaseContextDC(hdc);
  498.             return FALSE;
  499.         }
  500.  
  501.         // Windows bitmap files don't allow for a mask. Therefore we have to set the transparent
  502.         // parts of the image to be the appropriate color. This ensures that the bitmap file matches
  503.         // what the user sees on the screen
  504.         //
  505.         // ZZZ: This code should be shared with the code in _StretchBlt()
  506.         LO_Color*    bg = (pLOImage->text_attr && !pLOImage->text_attr->no_background) ? &pLOImage->text_attr->bg : NULL;
  507.         COLORREF    bgColor = bg ? RGB(bg->red, bg->green, bg->blue) : m_rgbBackgroundColor;
  508.  
  509.         if (maskinfo && maskinfo->hBitmap) {
  510.             HBRUSH    hBrush;
  511.             HDC tempDC = ::CreateCompatibleDC(hdc);
  512.             HBITMAP tempBmp = ::CreateCompatibleBitmap(hdc, lpBmi->biWidth, lpBmi->biHeight);
  513.             HBITMAP    hOldBmp = (HBITMAP)::SelectObject(tempDC, tempBmp);
  514.             HBITMAP    hOldBmp1 = (HBITMAP)::SelectObject(m_pImageDC, imageinfo->hBitmap);
  515.         
  516.             if (m_iBitsPerPixel == 16)
  517.                 // We don't want a dithered brush
  518.                 hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, bgColor));
  519.             else
  520.                 hBrush = ::CreateSolidBrush(0x02000000L | bgColor);
  521.             ::BitBlt(tempDC, 0, 0,lpBmi->biWidth, lpBmi->biHeight, m_pImageDC, 0, 0, SRCCOPY);
  522.  
  523.                 // Select the mask into the memory DC
  524.             ::SelectObject(m_pImageDC, maskinfo->hBitmap);
  525.  
  526.             // Change the transparent bits of the source bitmap to the desired background
  527.             // color by doing an AND raster op
  528.             //
  529.             // The mask is monochrome and will be converted to color to match the depth of
  530.             // the destination. The foreground pixels in the mask are set to 1, and the
  531.             // background pixels to 0. When converting to a color bitmap, white pixels (1)
  532.             // are set to the background color of the DC, and black pixels (0) are set to
  533.             // the text color of the DC
  534.             //
  535.             // Select the brush
  536.             HBRUSH    hOldBrush = (HBRUSH)::SelectObject(tempDC, hBrush);
  537.  
  538.             // Draw the brush where the mask is 0
  539.             ::BitBlt(tempDC,
  540.                            0,
  541.                            0,
  542.                            lpBmi->biWidth,
  543.                            lpBmi->biHeight,
  544.                            m_pImageDC,
  545.                            0,
  546.                            0,
  547.                            MAKEROP4(SRCPAINT, R2_COPYPEN));
  548.  
  549.             ::SelectObject(tempDC, hOldBrush);
  550.  
  551.             ::DeleteObject(hBrush);
  552.             ::GetDIBits(tempDC, tempBmp, 0, (int)lpBmi->biHeight, lpBits, (LPBITMAPINFO)lpBmi, DIB_RGB_COLORS);
  553.             ::SelectObject(m_pImageDC, hOldBmp1);
  554.             ::SelectObject(tempDC, hOldBmp);
  555.             ::DeleteObject(tempBmp);
  556.             ::DeleteDC(tempDC);
  557.         }
  558.         else
  559.         // This time have the driver give us the color table and the bits
  560.         ::GetDIBits(hdc, imageinfo->hBitmap, 0, (int)lpBmi->biHeight, lpBits, (LPBITMAPINFO)lpBmi, DIB_RGB_COLORS);
  561.         ReleaseContextDC(hdc);
  562.  
  563.         BITMAPFILEHEADER  bf;
  564.  
  565.         // Initialize the BITMAPFILEHEADER struct
  566.         bf.bfType = 0x4D42;  // 'BM'
  567.         bf.bfReserved1 = 0;
  568.         bf.bfReserved2 = 0;
  569.  
  570.         // Compute the offset to the bits. The bits are after the color table
  571.         bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nColorTable * sizeof(RGBQUAD);
  572.  
  573.         // Compute the size of the file
  574.         bf.bfSize = bf.bfOffBits + lpBmi->biSizeImage;
  575.  
  576.         // Open the file and start writing
  577.         CStdioFile    file;
  578.  
  579.         TRY {
  580. #ifndef XP_WIN32
  581.             file.Open(lpszFileName, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary);
  582. #else
  583.             file.Open(lpszFileName, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary | CFile::shareExclusive);
  584. #endif
  585.             // Write the BITMAPFILEHEADER structure
  586.             file.Write(&bf, sizeof(bf));
  587.     
  588.             // Write the BITMAPINFOHEADER and color table
  589.             file.Write(lpBmi, sizeof(BITMAPINFOHEADER) + nColorTable * sizeof(RGBQUAD));
  590.     
  591.             // Write the bits
  592. #ifdef XP_WIN32
  593.             file.Write(lpBits, lpBmi->biSizeImage);
  594. #else
  595.             file.WriteHuge(lpBits, lpBmi->biSizeImage);
  596. #endif
  597.             file.Close();
  598.         }
  599.         CATCH(CFileException, e) {
  600.             CDCCX::HugeFree(lpBits);
  601.             free(lpBmi);
  602.             return FALSE;
  603.         }
  604.         END_CATCH
  605.  
  606.         // Free up everything and return success
  607.         CDCCX::HugeFree(lpBits);
  608.         free(lpBmi);
  609.         return TRUE;
  610.     }
  611.     return FALSE;
  612. }
  613.  
  614.  
  615. void CDCCX::LayoutNewDocument(MWContext *pContext, URL_Struct *pURL, int32 *pWidth, int32 *pHeight, int32 *pmWidth, int32 *pmHeight)    {
  616.     //    Set up the width, height, and margins as defualt values here.
  617.     //    These should have been set up in the Initialize() member of a derived
  618.     //        class.
  619.     if (pContext->grid_children) {
  620.         XP_ListDestroy (pContext->grid_children);
  621.         pContext->grid_children = 0;
  622.     }
  623.     *pWidth = m_lWidth;
  624.     *pHeight = m_lHeight;
  625.  
  626.     //    No known margins, up to dervied classes to correctly set.
  627.     //    Don't set the margins if non-zero, Layout has it's own ideas about this.
  628.  
  629.     //    Set ourselves to be at the top of the document.
  630.     m_lOrgX = 0;
  631.     m_lOrgY = 0;
  632.  
  633.     //    Document has no substance.
  634.     m_lDocWidth = 0;
  635.     m_lDocHeight = 0;
  636.  
  637.  
  638.     //    Flush the background color.
  639.     COLORREF rgbColor = prefInfo.m_rgbBackgroundColor;
  640.     FE_SetBackgroundColor(pContext, GetRValue(rgbColor), GetGValue(rgbColor), GetBValue(rgbColor));
  641.  
  642.     //    We're loading a new page, so flush the previous page's
  643.     //        fonts so that we don't keep building a huge font cache.
  644.     ClearFontCache();
  645.  
  646. }
  647.  
  648. #define LIGHT_GRAY    RGB(192, 192, 192)
  649. #define DARK_GRAY    RGB(128, 128, 128)
  650. #define WHITE        RGB(255, 255, 255)
  651. #define BLACK        RGB(0, 0, 0)
  652.  
  653. static void
  654. GetSystem3DColors(COLORREF rgbBackground, COLORREF& rgbLightColor, COLORREF& rgbDarkColor)
  655. {
  656. #ifdef XP_WIN32
  657.     if (sysInfo.IsWin4_32()) {
  658.         // These are Windows 95 only
  659.         rgbLightColor = ::GetSysColor(COLOR_3DLIGHT);
  660.         rgbDarkColor = ::GetSysColor(COLOR_3DSHADOW);
  661.     } else {
  662.         rgbLightColor = LIGHT_GRAY;
  663.         rgbDarkColor = ::GetSysColor(COLOR_BTNSHADOW);
  664.     }
  665. #else
  666.     rgbLightColor = LIGHT_GRAY;
  667.     rgbDarkColor = ::GetSysColor(COLOR_BTNSHADOW);
  668. #endif
  669.  
  670.     // We need to make sure that both colors are visible against
  671.     // the background
  672.     if (rgbLightColor == rgbBackground)
  673.         rgbLightColor = rgbBackground == LIGHT_GRAY ? WHITE : LIGHT_GRAY;
  674.  
  675.     if (rgbDarkColor == rgbBackground)
  676.         rgbDarkColor = rgbBackground == DARK_GRAY ? BLACK : DARK_GRAY;
  677. }
  678.  
  679. // Constants for calculating Highlight (TS = "TopShadow") and
  680. //   shadow (BS = "BottomShadow") values relative to background
  681. // Taken from UNIX version -- Eric Bina's Visual.c
  682. //
  683. // Bias brightness calculation by standard color-sensitivity values
  684. // (Percents -- UNIX used floats, but we don't need to)
  685. //
  686. #define RED_LUMINOSITY 30
  687. #define GREEN_LUMINOSITY 59
  688. #define BLUE_LUMINOSITY 11
  689.  
  690. // Percent effect of intensity, light, and luminosity & on brightness,
  691. #define INTENSITY_FACTOR  25
  692. #define LIGHT_FACTOR       0
  693. #define LUMINOSITY_FACTOR 75
  694.  
  695. // LITE color model percent to interpolate RGB towards black for BS, TS
  696.  
  697. #define COLOR_LITE_BS_FACTOR   45
  698. #define COLOR_LITE_TS_FACTOR   70
  699.  
  700. // DARK color model - percent to interpolate RGB towards white for BS, TS
  701.  
  702. #define COLOR_DARK_BS_FACTOR   30
  703. #define COLOR_DARK_TS_FACTOR   50
  704. #define MAX_COLOR 255
  705.  
  706. #define COLOR_DARK_THRESHOLD   51
  707. #define COLOR_LIGHT_THRESHOLD  204
  708.  
  709. void CDCCX::Compute3DColors(COLORREF rgbColor, COLORREF &rgbLight, COLORREF &rgbDark)
  710. {
  711.     unsigned uRed, uGreen, uBlue;
  712.     unsigned uRedBack = GetRValue(rgbColor);
  713.     unsigned uGreenBack = GetGValue(rgbColor);
  714.     unsigned uBlueBack = GetBValue(rgbColor);
  715.     unsigned intensity = (uRedBack + uGreenBack + uBlueBack) / 3;
  716.     unsigned luminosity = ((RED_LUMINOSITY * uRedBack)/ 100)
  717.                      + ((GREEN_LUMINOSITY * uGreenBack)/ 100)
  718.                      + ((BLUE_LUMINOSITY * uBlueBack)/ 100);
  719.     unsigned backgroundBrightness = ((intensity * INTENSITY_FACTOR) +
  720.                    (luminosity * LUMINOSITY_FACTOR)) / 100;
  721.     unsigned f;
  722.     
  723.     if (backgroundBrightness < COLOR_DARK_THRESHOLD) {
  724.         // Dark Background - interpolate 30% toward black
  725.         uRed =  uRedBack - (COLOR_DARK_BS_FACTOR * uRedBack / 100);
  726.         uGreen = uGreenBack - (COLOR_DARK_BS_FACTOR * uGreenBack / 100);
  727.         uBlue = uBlueBack - (COLOR_DARK_BS_FACTOR * uBlueBack / 100);
  728.  
  729.         rgbDark = RGB(uRed, uGreen, uBlue);
  730.  
  731.         // This interpolotes to 50% toward white
  732.         uRed = uRedBack + (COLOR_DARK_TS_FACTOR *
  733.             (MAX_COLOR - uRedBack) / 100);
  734.         uGreen = uGreenBack + (COLOR_DARK_TS_FACTOR *
  735.             (MAX_COLOR - uGreenBack) / 100);
  736.  
  737.         uBlue = uBlueBack + (COLOR_DARK_TS_FACTOR *
  738.             (MAX_COLOR - uBlueBack) / 100);
  739.  
  740.     } else if (backgroundBrightness > COLOR_LIGHT_THRESHOLD) {
  741.         // Interpolate 45% toward black
  742.         uRed = uRedBack - (COLOR_LITE_BS_FACTOR * uRedBack / 100);
  743.         uGreen = uGreenBack - (COLOR_LITE_BS_FACTOR * uGreenBack / 100);
  744.         uBlue = uBlueBack - (COLOR_LITE_BS_FACTOR * uBlueBack / 100);
  745.         rgbDark = RGB(uRed, uGreen, uBlue);
  746.  
  747.         // Original algorithm (from X source: visual.c) used:
  748.         // uRed = uRedBack - (COLOR_LITE_TS_FACTOR * uRedBack / 100),
  749.         //   where FACTOR is 20%, but that makes no sense!
  750.         // I think the intention was large interpolation toward white,
  751.         //  so use max of "medium" range (70%) for smooth continuity across threshhold
  752.       uRed = uRedBack + (COLOR_LITE_TS_FACTOR * (MAX_COLOR - uRedBack) / 100);
  753.       uGreen = uGreenBack + (COLOR_LITE_TS_FACTOR * (MAX_COLOR - uGreenBack) / 100);
  754.       uBlue = uBlueBack + (COLOR_LITE_TS_FACTOR * (MAX_COLOR - uBlueBack) / 100);
  755.     
  756.     } else {
  757.         // Medium Background
  758.         f = COLOR_DARK_BS_FACTOR + (backgroundBrightness 
  759.                         * ( COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR )
  760.                         / MAX_COLOR);
  761.  
  762.         uRed = uRedBack - (f * uRedBack / 100);
  763.         uGreen = uGreenBack - (f * uGreenBack / 100);
  764.         uBlue = uBlueBack - (f * uBlueBack / 100);
  765.         rgbDark = RGB(uRed, uGreen, uBlue);
  766.  
  767.         f = COLOR_DARK_TS_FACTOR + (backgroundBrightness
  768.                        * ( COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR )
  769.                        / MAX_COLOR);
  770.  
  771.         uRed = uRedBack + (f * (MAX_COLOR - uRedBack) / 100);
  772.         uGreen = uGreenBack + (f * (MAX_COLOR - uGreenBack) / 100);
  773.         uBlue = uBlueBack + (f * (MAX_COLOR - uBlueBack) / 100);
  774.     }
  775.     
  776.     // Safety check for upper limit
  777.     uRed = min(MAX_COLOR, uRed);
  778.     uGreen = min(MAX_COLOR, uGreen);
  779.     uBlue = min(MAX_COLOR, uBlue);
  780.  
  781.     rgbLight = RGB(uRed, uGreen, uBlue);
  782.  
  783.     // If either of these colors is the same as the background color
  784.     // then use the system 3D element colors instead
  785.     if (rgbLight == m_rgbBackgroundColor || rgbDark == m_rgbBackgroundColor) {
  786.         GetSystem3DColors(m_rgbBackgroundColor, rgbLight, rgbDark);
  787.     }
  788. }
  789.  
  790. void CDCCX::Set3DColors(COLORREF crBackground)
  791. {
  792.     Compute3DColors(crBackground, m_rgbLightColor, m_rgbDarkColor);
  793. }
  794.  
  795. void CDCCX::SetBackgroundColor(MWContext *pContext, uint8 uRed, uint8 uGreen, uint8 uBlue)
  796. {
  797.     //    Generate the color reference
  798.     COLORREF crBackground = ResolveBGColor(uRed, uGreen, uBlue);
  799.     
  800.     if( crBackground != m_rgbBackgroundColor ){
  801.         // Recalculate the color only if it has changed
  802.         m_rgbBackgroundColor =  crBackground;
  803.         Set3DColors(m_rgbBackgroundColor);
  804.     }        
  805.  
  806.     //    Determine transparency.
  807.     ResolveTransparentColor(uRed, uGreen, uBlue);
  808.     
  809.     //    Set the background color in the DC.
  810.     HDC hdc = GetContextDC();
  811.     if (hdc) {
  812.         ::SetBkColor(hdc, m_rgbBackgroundColor);
  813.     }
  814. #ifdef DDRAW
  815.     if (GetPrimarySurface()) {
  816.         hdc = GetDispDC();  // set the background color for offscreen surface.
  817.         if (hdc) {
  818.             ::SetBkColor(hdc, m_rgbBackgroundColor);
  819.         }
  820.     }
  821. #endif
  822.     ReleaseContextDC(hdc);
  823.     
  824.     //    Have any views (ledges) clear.
  825.     //    Only do the FE_VIEW, since there aren't any other ledges right now.
  826.     FE_ClearView(pContext, FE_VIEW);
  827. }
  828.  
  829.  
  830. void CDCCX::SetTransparentColor(BYTE red, BYTE green, BYTE blue)
  831. {
  832.     rgbTransparentColor.red = red;
  833.     rgbTransparentColor.green = green;
  834.     rgbTransparentColor.blue = blue;
  835. }
  836.  
  837. // Create the initial identity palette that contains just the system colors
  838. // and the  colors.
  839. HPALETTE
  840. CDCCX::InitPalette(HDC hdc) 
  841. {
  842.     int i;
  843.     HPALETTE hPal;
  844.     //    Create an identity palette
  845.     LPLOGPALETTE pLogPal = (LPLOGPALETTE)XP_ALLOC(sizeof(LOGPALETTE)
  846.                                                   + 256 * sizeof(PALETTEENTRY));
  847.     if(pLogPal != NULL)    {
  848.         pLogPal->palVersion = 0x300;
  849.         pLogPal->palNumEntries = 256;
  850.         
  851.         // Get entries 0-9 and 246-255, which are the standard system colors
  852.         GetSystemPaletteEntries(hdc, 0, pLogPal->palNumEntries,
  853.                                 pLogPal->palPalEntry);
  854.  
  855.         // Initialize palette entry flags
  856.         for (i = 10; i < 246; i++) {
  857.             pLogPal->palPalEntry[i].peFlags = PALETTEENTRY_FLAGS;
  858. #ifndef USE_IDENTITY_PALETTE
  859.             // Collapse all unspecified entries to black so that we are
  860.             // friendlier to other applications sharing the palette.
  861.             if(i >= (iLowerColors + MAX_IMAGE_PALETTE_ENTRIES)) {
  862.                 pLogPal->palPalEntry[i].peRed   = 0;
  863.                 pLogPal->palPalEntry[i].peGreen = 0;
  864.                 pLogPal->palPalEntry[i].peBlue  = 0;
  865.             }
  866. #endif
  867.         }
  868.  
  869.         // Now add in the animation colors
  870.         for(int iLowCnt = iLowerSystemColors, j = 0; iLowCnt <
  871.                 iLowerColors; iLowCnt++, j++)    {
  872.             pLogPal->palPalEntry[iLowCnt].peRed   = animationPalette[j].red;
  873.             pLogPal->palPalEntry[iLowCnt].peGreen = animationPalette[j].green;
  874.             pLogPal->palPalEntry[iLowCnt].peBlue  = animationPalette[j].blue;
  875.             pLogPal->palPalEntry[iLowCnt].peFlags = PC_NOCOLLAPSE;
  876.         }
  877.         
  878.         
  879.         if(!(hPal = ::CreatePalette(pLogPal)))    {
  880.             hPal = NULL;
  881.         }
  882.  
  883.         
  884.         //    Done with this.
  885.         XP_FREE(pLogPal);
  886.     }
  887.     return hPal;
  888. }
  889. HPALETTE CDCCX::CreateColorPalette(HDC hdc, IL_IRGB& transparentColor, int bitsPerPixel)
  890. {
  891.     HPALETTE hPal;
  892.     //    Set up the per-context palette.
  893.     //    This is per-window since not everything goes to the screen, and therefore
  894.     //        won't always have the screen's attributes. (printing, metafiles DCs, etc).
  895.     IL_ColorMap * defaultColorMap =  IL_NewCubeColorMap(NULL, 0,
  896.                    MAX_IMAGE_PALETTE_ENTRIES+1);
  897.     hPal = CDCCX::InitPalette(hdc);
  898.     CDCCX::SetColormap(hdc, defaultColorMap, transparentColor, hPal);
  899.     IL_DestroyColorMap (defaultColorMap);
  900.  
  901.     return hPal;
  902. }
  903.  
  904.  
  905. void CDCCX::SetColormap(HDC hdc, NI_ColorMap *pMap, IL_IRGB& transparentColor, HPALETTE hPal) {
  906.  
  907.     PALETTEENTRY paletteEntries[256];
  908.     int iExactMatches = 0;      // # of color requests we were able to match
  909.     int iFirstImageColor = iLowerColors;
  910.     int iLastImageColor = iLowerColors + MAX_IMAGE_PALETTE_ENTRIES - 1;
  911.     // Copy existing palette to get system colors and animation colors
  912.     GetPaletteEntries(hPal, 0, 256, paletteEntries);
  913.     if (!pMap->index) {    // setup the index array.
  914.         pMap->index = (unsigned char*)XP_ALLOC(MAX_IMAGE_PALETTE_ENTRIES+1);
  915.         for (int i = 0; i < MAX_IMAGE_PALETTE_ENTRIES; i++) {
  916.             pMap->index[i] = iLowerColors + i;
  917.             paletteEntries[iLowerColors + i].peRed = pMap->map[i].red;
  918.             paletteEntries[iLowerColors + i].peGreen = pMap->map[i].green;
  919.             paletteEntries[iLowerColors + i].peBlue = pMap->map[i].blue;
  920.             paletteEntries[iLowerColors + i].peFlags = PALETTEENTRY_FLAGS;
  921.         }
  922.     }
  923.     paletteEntries[iLowerColors + MAX_IMAGE_PALETTE_ENTRIES].peRed = transparentColor.red;
  924.     paletteEntries[iLowerColors + MAX_IMAGE_PALETTE_ENTRIES].peGreen = transparentColor.green;
  925.     paletteEntries[iLowerColors + MAX_IMAGE_PALETTE_ENTRIES].peBlue = transparentColor.blue;
  926.     paletteEntries[iLowerColors + MAX_IMAGE_PALETTE_ENTRIES].peFlags = PC_NOCOLLAPSE;
  927.  
  928.     paletteEntries[255].peRed = 0xFF;
  929.     paletteEntries[255].peGreen = 0xFF;
  930.     paletteEntries[255].peBlue = 0xFF;
  931.     paletteEntries[255].peFlags = PALETTEENTRY_FLAGS;
  932.     
  933.     ::SetPaletteEntries(hPal, iFirstImageColor, MAX_IMAGE_PALETTE_ENTRIES,
  934.                             &paletteEntries[iFirstImageColor]);
  935. }
  936.  
  937. void CDCCX::SetDocDimension(MWContext *pContext, int iLocation, int32 lWidth, int32 lLength)    {
  938.     //    Set the document height and width.
  939.     m_lDocWidth = lWidth;
  940.     m_lDocHeight = lLength;
  941. }
  942.  
  943. void CDCCX::GetDocPosition(MWContext *pContext, int iLocation, int32 *lX_p, int32 *lY_p)    {
  944.     *lX_p = m_lOrgX;
  945.     *lY_p = m_lOrgY;
  946. }
  947.  
  948. BOOL CDCCX::OnOpenDocumentCX(const char *pPathName)    {
  949.     //    Should only happen with window contexts.
  950.     if(IsWindowContext() == FALSE)    {
  951.         return(FALSE);
  952.     }
  953.  
  954.     //    Make sure there's something specified, otherwise just
  955.     //        return sucess.
  956.     //    Take passing in NULL as a request to initialize, which we do
  957.     //        nothing with.
  958.     if(pPathName != NULL)    {
  959.         //    convert the path name to a URL.
  960.         CString csUrl;
  961.         WFE_ConvertFile2Url(csUrl, pPathName);
  962.  
  963.         //    Load it.
  964.         GetUrl(NET_CreateURLStruct(csUrl, NET_DONT_RELOAD), FO_CACHE_AND_PRESENT);
  965.     }
  966.     return(TRUE);
  967. }
  968.  
  969. void CDCCX::ViewImages()    {
  970.     if(IsDestroyed() == FALSE)    {
  971.         // Tell layout that all images are to be force loaded.
  972.         LO_SetForceLoadImage(NULL, TRUE);
  973.  
  974.         ExplicitlyLoadAllImages();
  975.     }
  976. }
  977.  
  978. BOOL CDCCX::CanViewImages()    {
  979.     BOOL bRetval;
  980.       if(prefInfo.m_bAutoLoadImages || IsDestroyed())    {
  981.           bRetval = FALSE;
  982.       }
  983.     else    {
  984.         bRetval = TRUE;
  985.     }
  986.  
  987.     return(bRetval);
  988. }
  989.  
  990. //    Set up the things that need to be in order to handle an OLE server
  991. //        metafile correctly.
  992. void CDCCX::EnableOleServer()
  993. {
  994.     TRACE("Enabling context as an OLE server\n");
  995.  
  996.     //    Mark a generic switch that can be checked elsewhere.
  997.     m_bOleServer = TRUE;
  998. }
  999.  
  1000. //    Create a url struct from the history, with appropriate checking
  1001. //        for NULL and such, so that we don't have this code scattered
  1002. //        throughout the client.
  1003. //    bClearStateData is a flag set to erase any data that can't be
  1004. //        tossed around without upsetting the client (form data).
  1005. //    It's off by default, so be careful out there.
  1006. URL_Struct *CDCCX::CreateUrlFromHist(BOOL bClearStateData, SHIST_SavedData *pSavedData, BOOL bWysiwyg)
  1007. {
  1008.     //    Make sure that we're not destroyed.
  1009.     if(IsDestroyed())    {
  1010.         return(NULL);
  1011.     }
  1012.  
  1013.     //    Before we create the URL, we must save any state data of the current page
  1014.     //        that is needed to perform the next load (such as position)....
  1015.     //    Other's not dealing with history, save their data in the GetUrl call.
  1016.     SHIST_SetPositionOfCurrentDoc(&(GetContext()->hist), 0);
  1017.     if(GetOriginX() || GetOriginY())    {
  1018. #ifdef LAYERS
  1019.         LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(GetDocumentContext(), GetOriginX(), GetOriginY(), NULL);
  1020. #else
  1021.         LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(GetDocumentContext(), GetOriginX(), GetOriginY());
  1022. #endif  /* LAYERS */
  1023.         if(pAny != NULL)    {
  1024.             TRACE("Remembering document position at element id %ld\n", pAny->ele_id);
  1025.             SHIST_SetPositionOfCurrentDoc(&(GetContext()->hist), pAny->ele_id);
  1026.         }
  1027.     }
  1028.  
  1029.     //    Call/return the base.
  1030.     URL_Struct *pUrl = CStubsCX::CreateUrlFromHist(bClearStateData, pSavedData, bWysiwyg);
  1031.     return(pUrl);
  1032. }
  1033.  
  1034. //
  1035. // Make the given form element visible on the screen
  1036. //
  1037. void CDCCX::DisplayFormElement(MWContext *pContext, int iLocation, LO_FormElementStruct *pFormElement) 
  1038. {
  1039.     //  Call the base.
  1040.     CStubsCX::DisplayFormElement(pContext, iLocation, pFormElement);
  1041.  
  1042.     //  Figure the coordinates.
  1043.     LTRB Rect;
  1044.  
  1045.     // Note that we call this version of ResolveElement since we do
  1046.     // something special for form elements. Note also that we don't
  1047.     // check the return value since this function may be called before
  1048.     // the form element is actually visible, but we have to correctly
  1049.     // "display". In other words, this function is only called when the
  1050.     // visibility or position of the form element changes and we need
  1051.     // make the corresponding changes to the actual widget irrespective
  1052.     // of whether it's visible or not.
  1053.     ResolveElement(Rect, pFormElement);
  1054.     
  1055.     SafeSixteen(Rect);
  1056.     
  1057.     //    Get our front end form element, and have it display itself at the given rectangle.
  1058.     CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(GetContext()), pFormElement);
  1059.     if(pFormClass != NULL)    {
  1060.         pFormClass->DisplayFormElement(Rect);
  1061.     }
  1062. }
  1063.  
  1064. void CDCCX::FormTextIsSubmit(MWContext *pContext, LO_FormElementStruct *pFormElement)  
  1065. {
  1066.     //  Call the base.
  1067.     CStubsCX::FormTextIsSubmit(pContext, pFormElement);
  1068.  
  1069.     //    Get our front end form element, and have it do it's thang.
  1070.     CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(GetContext()), pFormElement);
  1071.     if(pFormClass != NULL)    {
  1072.         pFormClass->FormTextIsSubmit();
  1073.     }
  1074. }
  1075.  
  1076. void CDCCX::GetFormElementInfo(MWContext *pContext, LO_FormElementStruct *pFormElement)    
  1077. {
  1078.  
  1079.     //  Call the base.
  1080.     CStubsCX::GetFormElementInfo(pContext, pFormElement);
  1081.  
  1082.     //    Get our front end form element, and have it do it's thang.
  1083.     CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(GetContext()), pFormElement);
  1084.     if(pFormClass != NULL)    {
  1085.         pFormClass->GetFormElementInfo();
  1086.     }
  1087. }
  1088.  
  1089.  
  1090. void CDCCX::GetFormElementValue(MWContext *pContext, LO_FormElementStruct *pFormElement, XP_Bool bTurnOff)
  1091. {
  1092.  
  1093.     //  Call the base.
  1094.     CStubsCX::GetFormElementValue(pContext, pFormElement, bTurnOff);
  1095.     
  1096.     //    Get our front end form element, and have it do it's thang.
  1097.     CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(GetContext()), pFormElement);
  1098.     if(pFormClass != NULL)    {
  1099.         pFormClass->GetFormElementValue(bTurnOff);
  1100.     }
  1101. }
  1102.  
  1103. void CDCCX::ResetFormElement(MWContext *pContext, LO_FormElementStruct *pFormElement)  
  1104. {
  1105.     //  Call the base.
  1106.     CStubsCX::ResetFormElement(pContext, pFormElement);
  1107.                               
  1108.     //    Get our front end form element, and have it do it's thang.
  1109.     CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(GetContext()), pFormElement);
  1110.     if(pFormClass != NULL)    {
  1111.         pFormClass->ResetFormElement();
  1112.     }
  1113.  
  1114. void CDCCX::SetFormElementToggle(MWContext *pContext, LO_FormElementStruct *pFormElement, XP_Bool iState)  
  1115. {
  1116.     //  Call the base.
  1117.     CStubsCX::SetFormElementToggle(pContext, pFormElement, iState);
  1118.  
  1119.     //    Get our front end form element, and have it do it's thang.
  1120.     CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(GetContext()), pFormElement);
  1121.     if(pFormClass != NULL)    {
  1122.         pFormClass->SetFormElementToggle(iState);
  1123.     }
  1124. }
  1125.  
  1126. //  Do a fill rect type operation.
  1127. void CDCCX::FloodRect(LTRB& Rect, HBRUSH hColor)
  1128. {
  1129.     if(hColor)  {
  1130.         HDC hdc = GetContextDC();
  1131.         if(hdc) {
  1132.             RECT cr;
  1133.             ::SetRect(&cr, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  1134.             ::FillRect(hdc, &cr, hColor);
  1135.             ReleaseContextDC(hdc);
  1136.         }
  1137.     }
  1138. }
  1139. BITMAPINFO* CDCCX::FillBitmapInfoHeader(NI_Pixmap* pImage)
  1140. {
  1141.     BITMAPINFO *pBMInfo;
  1142.  
  1143.     NI_PixmapHeader* imageHeader = &pImage->header;
  1144.     int pixmap_depth = imageHeader->color_space->pixmap_depth;
  1145.  
  1146.  
  1147.     if (pixmap_depth == 24 || pixmap_depth == 32)
  1148.         pBMInfo = (BITMAPINFO *)XP_ALLOC(sizeof(BITMAPINFOHEADER)+ (1 * sizeof(RGBQUAD))); // space for header only
  1149.     else if (pixmap_depth == 16)
  1150.         pBMInfo = (BITMAPINFO *)XP_ALLOC(sizeof(BITMAPINFOHEADER)+ (3 * sizeof(RGBQUAD)) ); // space for header and color masks
  1151.     else if (pixmap_depth == 8)
  1152.         pBMInfo = (BITMAPINFO *)XP_ALLOC(sizeof(BITMAPINFOHEADER)+ (256 * sizeof(RGBQUAD)) ); // space for header and pallette
  1153.     else if (pixmap_depth == 1) 
  1154.         pBMInfo = (BITMAPINFO *)XP_ALLOC(sizeof(BITMAPINFOHEADER)+ (2 * sizeof(RGBQUAD)) ); // space for header and pallette
  1155.     ASSERT(pixmap_depth < 32);
  1156.     if (!pBMInfo) return NULL; // error occor.
  1157.  
  1158.     pBMInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1159.     pBMInfo->bmiHeader.biWidth = pImage->header.width;
  1160.     pBMInfo->bmiHeader.biHeight = pImage->header.height;
  1161.     pBMInfo->bmiHeader.biPlanes = 1;
  1162.     pBMInfo->bmiHeader.biBitCount = (short)pixmap_depth;
  1163.  
  1164. #ifdef XP_WIN32
  1165.         //    Don't allow this to happen on OLE servers, as the metafiles can't
  1166.         //        handle it.
  1167.     if ((pixmap_depth > 1 ) && m_bRGB565) {
  1168.         pBMInfo->bmiHeader.biCompression = BI_BITFIELDS;
  1169.  
  1170.         // Define the color masks for a RGB565 DIB
  1171.         LPDWORD lpMasks = (LPDWORD)pBMInfo->bmiColors;
  1172.         lpMasks[0] = 0xF800;  // red color mask
  1173.         lpMasks[1] = 0x07E0;  // green color mask
  1174.         lpMasks[2] = 0x001F;  // blue color mask
  1175.  
  1176.     } else {
  1177.         if (pixmap_depth == 24 || pixmap_depth == 32) {
  1178.             LPDWORD lpMasks = (LPDWORD)pBMInfo->bmiColors;
  1179.             *lpMasks = NULL;
  1180.         }
  1181.  
  1182.         pBMInfo->bmiHeader.biCompression = BI_RGB;
  1183.     }
  1184. #else
  1185.     pBMInfo->bmiHeader.biCompression = BI_RGB;
  1186. #endif
  1187.  
  1188.     //pBMInfo->bmiHeader.biSizeImage = NULL;
  1189.     pBMInfo->bmiHeader.biSizeImage = pImage->header.widthBytes * pImage->header.height;
  1190.     pBMInfo->bmiHeader.biXPelsPerMeter = 0;
  1191.     pBMInfo->bmiHeader.biYPelsPerMeter = 0;
  1192.  
  1193.     pBMInfo->bmiHeader.biClrUsed = 0;        // default value    
  1194.     pBMInfo->bmiHeader.biClrImportant = 0;   // all important
  1195.  
  1196.     if(m_bUseDibPalColors) {
  1197.         if (pixmap_depth == 1) {
  1198.             // Build an index table for monochrome images. Only XBMs are
  1199.             // monochome
  1200.             WORD* pPalIndex = (WORD*)(pBMInfo->bmiColors);
  1201.  
  1202.             pPalIndex[0] = 255; // palette index for WHITE
  1203.             pPalIndex[1] = 0;   // palette index for BLACK
  1204.  
  1205.         } else {
  1206.             // pImage->depth != 1
  1207.             unsigned short nClrUsed = (unsigned short)(1 << pBMInfo->bmiHeader.biBitCount);
  1208.  
  1209.             // DIB_PAL_COLORS expects an array of 16-bit unsigned integers that specify
  1210.             // an index into the currently realized logical palette
  1211.             WORD* pPalIndx = (WORD*)(((unsigned char*)pBMInfo) + pBMInfo->bmiHeader.biSize);
  1212.             for (unsigned short index = 0; index < nClrUsed; index++, pPalIndx++)
  1213.                 *pPalIndx = index;
  1214.         }
  1215.  
  1216.     } else {
  1217.         // Not using DIB_PAL_COLORS
  1218.         if (pixmap_depth == 8) {
  1219.             RGBQUAD RGBArray[256];
  1220.             CopyPaletteToRGBArray(GetPalette(), RGBArray);
  1221.             memcpy(&(pBMInfo->bmiColors[0]), RGBArray, (256 * sizeof(RGBQUAD)));
  1222.  
  1223.  
  1224.  
  1225.         } else if (pixmap_depth == 1) {
  1226.             // Build the color table for monochrome images. Only XBMs are monochrome
  1227.             pBMInfo->bmiColors[0].rgbRed      = 255;
  1228.             pBMInfo->bmiColors[0].rgbGreen    = 255;
  1229.             pBMInfo->bmiColors[0].rgbBlue     = 255;
  1230.             pBMInfo->bmiColors[0].rgbReserved = 0;
  1231.             pBMInfo->bmiColors[1].rgbRed      = 0;
  1232.             pBMInfo->bmiColors[1].rgbGreen    = 0;
  1233.             pBMInfo->bmiColors[1].rgbBlue     = 0;
  1234.             pBMInfo->bmiColors[1].rgbReserved = 0;
  1235.         }
  1236.     }
  1237.     return pBMInfo;
  1238. }
  1239.  
  1240. static void replaceColorSpace(NI_Pixmap* pImage, NI_ColorSpace* curColorSpace, int devicePixmap)
  1241. {
  1242.     NI_PixmapHeader* imageHeader = &pImage->header;  
  1243.     NI_ColorSpace* color_space = imageHeader->color_space;  
  1244.  
  1245.     ASSERT(color_space->pixmap_depth  < 32);
  1246.     if (color_space->pixmap_depth == 1)
  1247.         return;
  1248.      if ((color_space->pixmap_depth <= 8) || (devicePixmap < color_space->pixmap_depth)) {
  1249.         IL_ReleaseColorSpace(color_space);
  1250.         IL_AddRefToColorSpace(curColorSpace);
  1251.         imageHeader->color_space = curColorSpace;
  1252.     }
  1253. }
  1254.  
  1255.  
  1256.  
  1257.  
  1258. static BOOL
  1259. CanCreateBrush(HBITMAP hBitmap, int nBitsPerPixel)
  1260. {
  1261.     BITMAP    bitmap;
  1262.  
  1263.     // Get the size of the bitmap
  1264.     ::GetObject(hBitmap, sizeof(bitmap), &bitmap);
  1265.  
  1266.     // We can create a brush if the bitmap is exacly 8x8 or we're on NT
  1267.     if (sysInfo.m_bWinNT) {
  1268.         if (nBitsPerPixel == 24) {
  1269.             // There's a reported problem with 24bpp mode on NT, but I haven't
  1270.             // seen it on NT 4.0
  1271. //            if (sysInfo.m_dwMajor < 4)
  1272.                 return FALSE;
  1273.         }
  1274.  
  1275.         // Large brushes on NT are a performance hog, so place an upper
  1276.         // limit on the brush size.
  1277.         return bitmap.bmWidth <= 64 && bitmap.bmHeight <= 64;
  1278.     }
  1279.  
  1280.      return bitmap.bmWidth == 8 && bitmap.bmHeight == 8;
  1281. }
  1282.  
  1283. HBITMAP CDCCX::CreateBitmap(HDC hTargetDC,  NI_Pixmap *image)
  1284. {
  1285.     ASSERT(hTargetDC);
  1286.     FEBitmapInfo    *imageInfo = (FEBitmapInfo*)image->client_data;
  1287.     
  1288.     BITMAPINFO *pBmInfo = imageInfo->bmpInfo;
  1289.  
  1290.     ASSERT(pBmInfo);
  1291.  
  1292.     return ::CreateDIBitmap(hTargetDC, &pBmInfo->bmiHeader, 
  1293.                 CBM_INIT, image->bits,
  1294.                 pBmInfo, m_bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS);
  1295.  
  1296. }
  1297.  
  1298.  
  1299. int CDCCX::DisplayPixmap(NI_Pixmap* image, NI_Pixmap* mask, int32 x, int32 y, int32 x_offset, int32 y_offset, int32 width, int32 height, LTRB& Rect)
  1300. {
  1301.     //    If width and height are 0, then we assume the entire width and height.
  1302.     //    x and y are relative coords to the top left of the image.
  1303.     HDC hdc;
  1304. #ifdef DDRAW
  1305.     LPDIRECTDRAWSURFACE drawSurface = GetBackSurface(); 
  1306. #endif
  1307.     hdc = GetDispDC();
  1308.  
  1309.     FEBitmapInfo *imageInfo = (FEBitmapInfo*) image->client_data;
  1310.  
  1311.     if (!imageInfo) return FALSE;  // there is no image to display.
  1312.  
  1313.     // set this flag, so the display boarder will not try to display the icon.
  1314.     imageInfo->imageDisplayed = TRUE;
  1315.     int    xRepeat, yRepeat;
  1316.     xRepeat = (CASTINT(width) + CASTINT(x_offset) + CASTINT(imageInfo->targetWidth) -1) / CASTINT(imageInfo->targetWidth);
  1317.     yRepeat = (CASTINT(height) + CASTINT(y_offset) + CASTINT(imageInfo->targetHeight) -1) / CASTINT(imageInfo->targetHeight);
  1318.     if (!ResolveElement(Rect, image, x_offset * m_lConvertX, y_offset *m_lConvertY, 
  1319.                             x * m_lConvertX, y* m_lConvertY, 
  1320.                             width* m_lConvertX, height* m_lConvertY))
  1321.         return FALSE;
  1322.     SafeSixteen(Rect);
  1323.  
  1324.     FEBitmapInfo *maskInfo = (FEBitmapInfo *)NULL;
  1325.  
  1326.     if (mask) maskInfo = (FEBitmapInfo *)mask->client_data;
  1327.  
  1328.  
  1329.  
  1330.     x_offset = (x_offset > 0) ? x_offset : 0;
  1331.     y_offset = (y_offset > 0) ? y_offset : 0; 
  1332.  
  1333.     if ((xRepeat > 1) || (yRepeat > 1)) { // tiled
  1334.         TileImage(hdc, Rect, image, mask, x * GetXConvertUnit(), y * GetYConvertUnit());
  1335.     }
  1336.     else {
  1337.         if (maskInfo) { 
  1338.             if ((imageInfo->hBitmap) && (maskInfo->hBitmap)) {
  1339. #ifdef XP_WIN32
  1340.                 if (sysInfo.m_bWinNT && (GetContextType() != MetaFile) && !IsPrintContext()) {
  1341.                     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(m_pImageDC, imageInfo->hBitmap);
  1342.                     // MaskBlt has two raster ops: one for the foreground pixels (value of 1)
  1343.                     // and one for the background pixels (value of 0). The raster op is
  1344.                     // specified using MAKEROP4(fore,back)
  1345.  
  1346. #ifdef USE_DIB_SECTION
  1347.                     if (image->bits)
  1348.                         ::MaskBlt(hdc,
  1349.                             CASTINT(Rect.left),
  1350.                             CASTINT(Rect.top),
  1351.                             CASTINT(Rect.right - Rect.left), 
  1352.                             CASTINT(Rect.bottom - Rect.top),
  1353.                             m_pImageDC, x_offset, y_offset,
  1354.                             maskInfo->hBitmap,
  1355.                             x_offset, y_offset,
  1356.                             MAKEROP4(SRCCOPY, 0x00AA0029));  // 0x00AA0029 is destination...
  1357.  
  1358.                     else 
  1359. #endif
  1360.                         ::MaskBlt(hdc,
  1361.                             CASTINT(Rect.left),
  1362.                             CASTINT(Rect.top),
  1363.                             CASTINT(Rect.right - Rect.left), 
  1364.                             CASTINT(Rect.bottom - Rect.top),
  1365.                             m_pImageDC, x_offset, y_offset,
  1366.                             maskInfo->hBitmap,
  1367.                             x_offset, y_offset,
  1368.                             MAKEROP4(0x00AA0029, SRCCOPY));  // 0x00AA0029 is destination...
  1369.  
  1370.                         // Cleanup
  1371.                     ::SelectObject(m_pImageDC, hOldBitmap);
  1372.                 }
  1373.                 else
  1374. #endif
  1375.                     StretchMaskBlt(hdc, imageInfo->hBitmap, maskInfo->hBitmap, 
  1376.                         CASTINT(Rect.left),     
  1377.                         CASTINT(Rect.top),
  1378.                         CASTINT(Rect.right - Rect.left), 
  1379.                         CASTINT(Rect.bottom - Rect.top),
  1380.                         x_offset,
  1381.                         y_offset, 
  1382.                         width, 
  1383.                         height);
  1384.             }
  1385.             else {
  1386.                 _StretchDIBitsWithMask(hdc,
  1387.                                 CASTINT(Rect.left),     
  1388.                                 CASTINT(Rect.top),
  1389.                                 CASTINT(Rect.right - Rect.left), 
  1390.                                 CASTINT(Rect.bottom - Rect.top),
  1391.                                 CASTINT(x_offset),
  1392.                                 // the reason for this calculation is that Window's bitmap
  1393.                                 // is reverse.  The first scan line will be at the buttom of
  1394.                                 // the bitmap buffer.
  1395.                                 CASTINT(imageInfo->height - ((height ) + y_offset)),
  1396.                                 CASTINT(width ),
  1397.                                 CASTINT(height),
  1398.                                 image,
  1399.                                 mask);
  1400.             }
  1401.         }
  1402.         else {
  1403.             StretchPixmap(hdc, image, 
  1404.                     CASTINT(Rect.left),     
  1405.                     CASTINT(Rect.top),
  1406.                     CASTINT(Rect.right - Rect.left), 
  1407.                     CASTINT(Rect.bottom - Rect.top),
  1408.                     x_offset,
  1409.                     y_offset, 
  1410.                     width, 
  1411.                     height);
  1412.  
  1413.         }
  1414.     }
  1415.     ReleaseContextDC(hdc);
  1416.  
  1417.  
  1418.     return 1;
  1419. }
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425. ///////////////////
  1426. // Destination coordinates are in the logical units of pDC, and
  1427. // the source coordinates are in device units
  1428. void CDCCX::StretchPixmap(HDC hTargetDC, NI_Pixmap* pImage, 
  1429.                                 int32 dx, int32 dy, int32 dw, int32 dh,
  1430.                                 int32 sx, int32 sy, int32 sw, int32 sh)
  1431. {
  1432.  
  1433.     
  1434.     // Clamp the width and height if necessary
  1435.     if (sx < 0 || sy < 0)
  1436.         return;
  1437.     FEBitmapInfo    *imageInfo = (FEBitmapInfo*)pImage->client_data;
  1438.     
  1439.     BITMAPINFO *pBmInfo = imageInfo->bmpInfo;
  1440.  
  1441.  
  1442.    if (imageInfo->hBitmap) {
  1443.         HBITMAP hOldBitmap;
  1444.         
  1445.         // If we are using this image as a tile, the bitmap will already be selected
  1446.         // into the memory DC for us.
  1447.         if (!imageInfo->IsTile)
  1448.             hOldBitmap = (HBITMAP)::SelectObject(m_pImageDC, imageInfo->hBitmap);
  1449.  
  1450.         ::StretchBlt(hTargetDC,
  1451.                             CASTINT(dx),
  1452.                             CASTINT(dy),
  1453.                             CASTINT(dw),
  1454.                             CASTINT(dh),
  1455.                             m_pImageDC,
  1456.                             CASTINT(sx),
  1457.                             CASTINT(sy),
  1458.                             CASTINT(sw),
  1459.                             CASTINT(sh),
  1460.                              pBmInfo->bmiHeader.biBitCount == 1 ? SRCAND : SRCCOPY);
  1461.         
  1462.         // If we are using this image as a tile, the bitmap will be deselected for us.
  1463.         if (!imageInfo->IsTile)
  1464.             ::SelectObject(m_pImageDC, hOldBitmap);
  1465.    }
  1466.    else {
  1467.  
  1468.         // the reason for this calculation is because window's bmp is an
  1469.         // upsidedown image.  the bit in the pImage->bits does reflect
  1470.         // this.  So we need to sepcify the offset from the bottom up.
  1471.         ::StretchDIBits( hTargetDC,
  1472.                             CASTINT(dx),
  1473.                             CASTINT(dy),
  1474.                             CASTINT(dw),
  1475.                             CASTINT(dh),
  1476.                             CASTINT(sx),
  1477.                             CASTINT(imageInfo->height - (sh + sy)),
  1478.                             CASTINT(sw),
  1479.                             CASTINT(sh),
  1480.                             pImage->bits,    // address of bitmap bits 
  1481.                             imageInfo->bmpInfo,    // address of bitmap data 
  1482.                             CASTUINT(m_bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS),
  1483.                              pBmInfo->bmiHeader.biBitCount == 1 ? SRCAND : SRCCOPY);
  1484.  
  1485.    }
  1486.         
  1487. }
  1488.  
  1489. HBITMAP CDCCX::CreateMask(HDC hTargetDC, NI_Pixmap* mask) 
  1490. {
  1491.  
  1492.     ASSERT(hTargetDC);
  1493.     FEBitmapInfo    *maskInfo = (FEBitmapInfo*)mask->client_data;
  1494.  
  1495.     // Build a BITMAPINFO struct for mask
  1496.     char          cMask[sizeof(BITMAPINFOHEADER) + (2 * sizeof(RGBQUAD))];
  1497.     LPBITMAPINFO pBmInfoMask = (LPBITMAPINFO)cMask;
  1498.         
  1499.     memcpy(pBmInfoMask, maskInfo->bmpInfo, sizeof(BITMAPINFOHEADER));
  1500.     pBmInfoMask->bmiHeader.biBitCount = 1;
  1501.     pBmInfoMask->bmiHeader.biCompression = BI_RGB;  // must NOT be BI_BITFIELDS
  1502.  
  1503.     pBmInfoMask->bmiColors[1] = rgbqBlack;  // background pixels
  1504.     pBmInfoMask->bmiColors[0] = rgbqWhite;  // foreground pixels
  1505.     // Create the mask. It's important that we use the memory DC, because we
  1506.     // want a momochrome bitmap
  1507.     return  ::CreateDIBitmap(hTargetDC,
  1508.                 (LPBITMAPINFOHEADER)pBmInfoMask,
  1509.                 CBM_INIT,
  1510.                 mask->bits,
  1511.                 pBmInfoMask,
  1512. //                m_bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS);
  1513.                 DIB_RGB_COLORS);
  1514. }
  1515.  
  1516. // StretchBlt a DIB with a mask
  1517. // Destination coordinates are in the logical units of pDC, and
  1518. // the source coordinates are in device units
  1519. void WFE_StretchDIBitsWithMask(HDC hTargetDC,
  1520.                             BOOL isDeviceDC,
  1521.                             HDC hOffscreenDC,
  1522.                             int dx,
  1523.                             int dy,
  1524.                             int dw,
  1525.                             int dh,
  1526.                             int sx,
  1527.                             int sy,
  1528.                             int sw,
  1529.                             int sh,
  1530.                             void XP_HUGE *imageBit,
  1531.                             BITMAPINFO* lpImageInfo,
  1532.                             void XP_HUGE *maskBit,
  1533.                             BOOL bUseDibPalColors,
  1534.                             COLORREF fillWithBackground
  1535.                             )
  1536. {
  1537.         // Tile the shadow bitmap with the backdrop
  1538.     HBITMAP pSaveBmp;
  1539.     HBITMAP bmpShadow;
  1540.     HDC hTempDC;
  1541.     int32 targetX, targetY;
  1542.     HDC memDC;
  1543.  
  1544.  
  1545.     if (isDeviceDC) {
  1546.  
  1547.         if (hOffscreenDC)
  1548.             memDC = hOffscreenDC;
  1549.         else {
  1550.             memDC = ::CreateCompatibleDC(hTargetDC);
  1551.         }
  1552.         if (!(bmpShadow = (HBITMAP)CreateCompatibleBitmap(hTargetDC, dw, dh))) {
  1553.             TRACE("_StretchBltWithMask() can't create bitmap!\n");
  1554.             return;
  1555.         }
  1556.         pSaveBmp = (HBITMAP) ::SelectObject(memDC, bmpShadow);
  1557.         if (!fillWithBackground) {
  1558.             ::StretchBlt(memDC,       // get the screen bit.
  1559.                 CASTINT(0), CASTINT(0), 
  1560.                 CASTINT(dw), CASTINT(dh), 
  1561.                 hTargetDC, 
  1562.                 CASTINT(dx), CASTINT(dy), 
  1563.                 CASTINT(dw), CASTINT(dh), 
  1564.                 SRCCOPY);
  1565.         } 
  1566.         else {  // the background is solid color.
  1567.             HBRUSH hbr = ::CreateSolidBrush(fillWithBackground);
  1568.             RECT tempRect;
  1569.             tempRect.left = tempRect.top = 0;
  1570.             tempRect.right = dw;
  1571.             tempRect.bottom = dh;
  1572.             ::FillRect(memDC, &tempRect, hbr);
  1573.             ::DeleteObject(hbr);
  1574.         }
  1575.         hTempDC = memDC;
  1576.         targetX = targetY = 0;
  1577.     }
  1578.     else  {
  1579.         hTempDC =  hTargetDC;
  1580.         targetX = dx;
  1581.         targetY = dy;
  1582.     }
  1583.  
  1584.     char          cMask[sizeof(BITMAPINFOHEADER) + (2 * sizeof(RGBQUAD))];
  1585.     LPBITMAPINFO pBmInfoMask = (LPBITMAPINFO)cMask;
  1586.  
  1587.     memcpy(pBmInfoMask, lpImageInfo, sizeof(BITMAPINFOHEADER));
  1588.     pBmInfoMask->bmiHeader.biBitCount = 1;
  1589.     pBmInfoMask->bmiHeader.biCompression = BI_RGB;  // must NOT be BI_BITFIELDS
  1590.  
  1591.     // Build a color table for monochrome mask. The image library sets foreground
  1592.     // pixels to 1 and background pixels to 0. We want it the other way around
  1593.     // when doing the AND operation
  1594.     pBmInfoMask->bmiColors[0] = rgbqWhite;  // background pixels
  1595.     pBmInfoMask->bmiColors[1] = rgbqBlack;  // foreground pixels
  1596.     pBmInfoMask->bmiHeader.biSizeImage =  0;
  1597.     int err = ::StretchDIBits(hTempDC,
  1598.                 CASTINT(targetX), CASTINT(targetY), 
  1599.                 CASTINT(dw), CASTINT(dh), 
  1600.                 CASTINT(sx), CASTINT(sy), 
  1601.                 CASTINT(sw), CASTINT(sh),
  1602.                 maskBit,
  1603.                 pBmInfoMask,
  1604.                 DIB_RGB_COLORS,
  1605.                 SRCAND);
  1606.     err = ::StretchDIBits(hTempDC,
  1607.                 CASTINT(targetX), CASTINT(targetY), 
  1608.                 CASTINT(dw), CASTINT(dh), 
  1609.                 CASTINT(sx), CASTINT(sy), 
  1610.                 CASTINT(sw), CASTINT(sh), 
  1611.                 imageBit,
  1612.                 lpImageInfo,
  1613.                 bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS,
  1614.                 SRCPAINT);
  1615.     if (isDeviceDC) {
  1616.  
  1617.         ::StretchBlt(hTargetDC,
  1618.                  CASTINT(dx), CASTINT(dy),
  1619.                  CASTINT(dw), CASTINT(dh), 
  1620.                  memDC,
  1621.                  CASTINT(0), CASTINT(0), 
  1622.                  CASTINT(dw),CASTINT(dh), 
  1623.                  SRCCOPY);
  1624.  
  1625.         ::SelectObject(memDC, pSaveBmp);
  1626.         VERIFY(::DeleteObject( bmpShadow));
  1627.         if (!hOffscreenDC) {    // Delete the temporary DC that we created.
  1628.             ::DeleteDC(memDC);
  1629.         }
  1630.     }
  1631. }
  1632.  
  1633.        
  1634. // StretchBlt a DIB with a mask
  1635. // Destination coordinates are in the logical units of pDC, and
  1636. // the source coordinates are in device units
  1637. void CDCCX::_StretchDIBitsWithMask(HDC hTargetDC,
  1638.                             int dx,
  1639.                             int dy,
  1640.                             int dw,
  1641.                             int dh,
  1642.                             int sx,
  1643.                             int sy,
  1644.                             int sw,
  1645.                             int sh,
  1646.                             NI_Pixmap *image,
  1647.                             NI_Pixmap *mask)
  1648. {
  1649.         // Tile the shadow bitmap with the backdrop
  1650.     FEBitmapInfo    *imageInfo = (FEBitmapInfo*)image->client_data;
  1651.     FEBitmapInfo    *maskInfo = (FEBitmapInfo*)mask->client_data;
  1652.     WFE_StretchDIBitsWithMask(hTargetDC, IsDeviceDC(), m_pImageDC, 
  1653.                                 dx, dy, dw, dh,
  1654.                                 sx, sy, sw, sh, 
  1655.                                 image->bits,
  1656.                                 imageInfo->bmpInfo,
  1657.                                 mask->bits,
  1658.                                 m_bUseDibPalColors);
  1659. }
  1660.  
  1661.        
  1662. void CDCCX::StretchMaskBlt(HDC hTargetDC, HBITMAP theBitmap, HBITMAP theMask, 
  1663.                                 int32 dx, int32 dy, int32 dw, int32 dh,
  1664.                                 int32 sx, int32 sy, int32 sw, int32 sh)
  1665. {
  1666.         // Tile the shadow bitmap with the backdrop
  1667.     HDC        memDC = NULL;
  1668.     HBITMAP pSaveBmp;
  1669.     HBITMAP bmpShadow;
  1670.     HPALETTE hOldPal1 = NULL;
  1671.     int32 targetX, targetY;
  1672.  
  1673.     if (IsDeviceDC()) {
  1674.  
  1675.  
  1676.         if (!(bmpShadow = (HBITMAP)CreateCompatibleBitmap(hTargetDC, CASTINT(dw), CASTINT(dh)))) {
  1677.             TRACE("_StretchBltWithMask() can't create bitmap!\n");
  1678.             return;
  1679.         }
  1680.         // Create memory DC
  1681.         if (!(memDC=CreateCompatibleDC(hTargetDC))) {
  1682.             TRACE("_StretchBltWithMask() can't create compatible memory DC!\n");
  1683.             return;
  1684.         }
  1685.         if (m_bUseDibPalColors && m_pPal)    {
  1686.             hOldPal1 = (HPALETTE)::SelectPalette(memDC, m_pPal, FALSE);
  1687.         }
  1688.  
  1689.     pSaveBmp = (HBITMAP) ::SelectObject(memDC, bmpShadow);
  1690.     ::StretchBlt(memDC,
  1691.                 CASTINT(0), CASTINT(0), 
  1692.                 CASTINT(dw), CASTINT(dh), 
  1693.                 hTargetDC, 
  1694.                 CASTINT(dx), CASTINT(dy), 
  1695.                 CASTINT(dw), CASTINT(dh), 
  1696.                 SRCCOPY);
  1697.         targetX = targetY = 0;
  1698.     }
  1699.     else {
  1700.         memDC = hTargetDC;
  1701.         targetX = dx;
  1702.         targetY = dy;
  1703.     }
  1704.     HBITMAP old = (HBITMAP)::SelectObject(m_pImageDC, theMask);
  1705.     ::StretchBlt(memDC,
  1706.                 CASTINT(targetX), CASTINT(targetY), 
  1707.                 CASTINT(dw), CASTINT(dh), 
  1708.                 m_pImageDC, 
  1709.                 CASTINT(sx), CASTINT(sy), 
  1710.                 CASTINT(sw), CASTINT(sh), 
  1711.                 SRCAND);
  1712.  
  1713.     // load the bitmap into the cached image CDC                                                   
  1714.     ::SelectObject(m_pImageDC, theBitmap);
  1715.  
  1716.     ::StretchBlt(memDC,
  1717.                 CASTINT(targetX), CASTINT(targetY), 
  1718.                 CASTINT(dw), CASTINT(dh), 
  1719.                 m_pImageDC, 
  1720.                 CASTINT(sx), CASTINT(sy), 
  1721.                 CASTINT(sw), CASTINT(sh), 
  1722.                 SRCPAINT);
  1723.  
  1724.     if (IsDeviceDC()) {
  1725.         ::StretchBlt(hTargetDC,
  1726.                  CASTINT(dx), CASTINT(dy),
  1727.                  CASTINT(dw), CASTINT(dh), 
  1728.                  memDC,
  1729.                  CASTINT(0), CASTINT(0), 
  1730.                  CASTINT(dw),CASTINT(dh), 
  1731.                  SRCCOPY);
  1732.         ::SelectObject(memDC, pSaveBmp);
  1733.         if (m_bUseDibPalColors && hOldPal1)    {
  1734.             ::SelectPalette(memDC, hOldPal1, FALSE);
  1735.         }
  1736.         VERIFY(::DeleteDC(memDC));
  1737.         VERIFY(::DeleteObject( bmpShadow));
  1738.     }
  1739.     ::SelectObject(m_pImageDC, old);
  1740.  
  1741. }
  1742.         
  1743. // We need to allocate the space for the image decoding ourselves because it 
  1744. // depends on what size machine we are on how we want to do it
  1745. BITMAPINFO *CDCCX::NewPixmap(NI_Pixmap *pImage, BOOL mask)
  1746. {
  1747.     if(mask == FALSE) {  
  1748.         replaceColorSpace(
  1749.             pImage,
  1750.             /*this->*/curColorSpace,
  1751.             /*this->*/m_iBitsPerPixel);
  1752.     }
  1753.  
  1754.     NI_PixmapHeader& header = pImage->header;
  1755.     NI_ColorSpace *& color_space = header.color_space;  
  1756.     uint8& pixmap_depth = color_space->pixmap_depth;
  1757.  
  1758.     if(pImage->bits == NULL) {
  1759.         header.widthBytes = header.width;
  1760.         header.widthBytes *= pixmap_depth;
  1761.         if(pixmap_depth < 8) {
  1762.             header.widthBytes += 7;
  1763.         }
  1764.         header.widthBytes /= 8;
  1765.  
  1766.         // Make sure image width is 4byte aligned
  1767.         int iAlign = CASTINT(header.widthBytes  % 4);
  1768.         if(iAlign)    {
  1769.             header.widthBytes += 4;
  1770.             header.widthBytes -= iAlign;
  1771.         }
  1772. //#ifndef XP_WIN32
  1773. #ifndef USE_DIB_SECTION
  1774.         // The image buffer might need to be really big (i.e. over 32K)
  1775.         // We need to use a huge memory allocation on the 16-bit version        
  1776.         pImage->bits = HugeAlloc(header.widthBytes * header.height, 1);
  1777.         // Note: It's possible that the image is so huge that we can't allocate enough
  1778.         // memory for it, especially under Win16 (e.g. 18 Mb images)
  1779.         if(pImage->bits == NULL) {
  1780.             return(NULL);
  1781.         }
  1782.         return(FillBitmapInfoHeader(pImage));
  1783. #else  // for use with createDibSection.
  1784.             BITMAPINFO* pbmInfo = FillBitmapInfoHeader(pImage);
  1785.             FEBitmapInfo *imageInfo;
  1786.             imageInfo = (FEBitmapInfo*) pImage->client_data;
  1787.             HDC hdc = GetContextDC();
  1788.             imageInfo->hBitmap = CreateDIBSection(hdc,
  1789.                 pbmInfo,    // pointer to structure containing bitmap size, format, and color data
  1790.                 m_bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS,
  1791.                 &pImage->bits,    // pointer to variable to receive a pointer to the bitmap's bit values
  1792.                 NULL,    // optional handle to a file mapping object
  1793.                 NULL    // offset to the bitmap bit values within the file mapping object
  1794.                 );
  1795.             ReleaseContextDC(hdc);
  1796. #ifdef DEBUG
  1797.             // If this assert fires, please be sure to report the following
  1798.             // information: pixmap_depth, header.widthBytes, header.height
  1799.             // and the current display setting - kevina.
  1800.             XP_ASSERT(pImage->bits);
  1801.  
  1802.             if (pImage->bits) {
  1803.             // Check whether the pointer is currently valid.
  1804.             XP_ASSERT(!IsBadWritePtr((void *)pImage->bits,
  1805.                                      (uint)(header.widthBytes*header.height)));
  1806.             XP_ASSERT(!IsBadReadPtr((void *)pImage->bits,
  1807.                                     (uint)(header.widthBytes*header.height)));
  1808.  
  1809.             // For testing.  Purify sometimes gets confused and complains that
  1810.             // the shared memory pointer returned by CreateDIBSection is
  1811.             // invalid, even though the previous assertions don't fire.  If
  1812.             // this happens, expect Purify to complain whenever the ImageLib
  1813.             // accesses the bits pointer.
  1814. //          memset(pImage->bits, ~0, (header.widthBytes * header.height));
  1815.             memset(pImage->bits, ~0, 1);
  1816.             }
  1817. #endif // DEBUG
  1818.  
  1819.             if (!imageInfo->hBitmap) {
  1820.                 return FALSE;
  1821.             }
  1822.             else
  1823.                 return pbmInfo;
  1824. #endif
  1825.         
  1826.     }  
  1827.  
  1828.     return NULL;
  1829. }
  1830.  
  1831.  
  1832.  
  1833. // Create a larger tile from a smaller one.  The dimensions of the larger
  1834. // tile must be a multiple of the dimensions of the smaller tile.
  1835. static HBITMAP CreateLargerTile(HDC pDC, HDC pMemDCNew, HDC pMemDCOld,
  1836.                                 NI_Pixmap *pImage, BOOL bUseDibPalColors,
  1837.                                 int iOldWidth, int iOldHeight,
  1838.                                 int iNewWidth, int iNewHeight)
  1839. {
  1840.     int x, y;
  1841.     HBITMAP pNewTile;
  1842.     HGDIOBJ pSavedObj1, pSavedObj2;
  1843.     FEBitmapInfo *imageInfo = (FEBitmapInfo *)pImage->client_data;
  1844.  
  1845.     pNewTile = CreateCompatibleBitmap(pDC, iNewWidth, iNewHeight);
  1846.     if (!pNewTile)
  1847.         return NULL;
  1848.     pSavedObj1 = (HGDIOBJ)::SelectObject(pMemDCNew, pNewTile);
  1849.     if (imageInfo->hBitmap) {
  1850.         pSavedObj2 = (HGDIOBJ)::SelectObject(pMemDCOld, imageInfo->hBitmap);
  1851.         ::BitBlt(pMemDCNew, 0, 0, iOldWidth, iOldHeight, pMemDCOld, 0, 0, SRCCOPY);
  1852.     }
  1853.     else {
  1854.         uint iUsage = bUseDibPalColors ? DIB_PAL_COLORS : DIB_RGB_COLORS;
  1855.  
  1856.         ::StretchDIBits(pMemDCNew, 0, 0, iOldWidth, iOldHeight, 0, 0, iOldWidth, iOldHeight,
  1857.                         pImage->bits, imageInfo->bmpInfo, iUsage, SRCCOPY);
  1858.     }
  1859.     // Fill up the new tile exponentially for speed.
  1860.     for    (x = iOldWidth; x < iNewWidth; x *= 2) {
  1861.         ::BitBlt(pMemDCNew, x, 0, MIN(x,iNewWidth-x), iOldHeight, pMemDCNew, 0, 0, SRCCOPY);
  1862.     }
  1863.     for    (y = iOldHeight; y < iNewHeight; y *= 2) {
  1864.         ::BitBlt(pMemDCNew, 0, y, iNewWidth, MIN(y,iNewHeight-y), pMemDCNew, 0, 0, SRCCOPY);
  1865.     }
  1866.     ::SelectObject(pMemDCNew, pSavedObj1);
  1867.     if (imageInfo->hBitmap)
  1868.         ::SelectObject(pMemDCOld, pSavedObj2);
  1869.  
  1870.     return pNewTile;
  1871. }
  1872. #ifdef DDRAW
  1873. /*
  1874.  * DDColorMatch
  1875.  *
  1876.  * convert a RGB color to a pysical color.
  1877.  *
  1878.  * we do this by leting GDI SetPixel() do the color matching
  1879.  * then we lock the memory and see what it got mapped to.
  1880.  */
  1881. static DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb)
  1882. {
  1883.     COLORREF rgbT;
  1884.     HDC hdc;
  1885.     DWORD dw = CLR_INVALID;
  1886.     DDSURFACEDESC ddsd;
  1887.     HRESULT hres;
  1888.  
  1889.     //
  1890.     //  use GDI SetPixel to color match for us
  1891.     //
  1892.     if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  1893.     {
  1894.         rgbT = GetPixel(hdc, 0, 0);             // save current pixel value
  1895.         SetPixel(hdc, 0, 0, rgb);               // set our value
  1896.         pdds->ReleaseDC(hdc);
  1897.     }
  1898.  
  1899.     //
  1900.     // now lock the surface so we can read back the converted color
  1901.     //
  1902.     ddsd.dwSize = sizeof(ddsd);
  1903.     while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
  1904.         ;
  1905.  
  1906.     if (hres == DD_OK)
  1907.     {
  1908.         dw  = *(DWORD *)ddsd.lpSurface;                     // get DWORD
  1909.         dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;  // mask it to bpp
  1910.         pdds->Unlock(NULL);
  1911.     }
  1912.  
  1913.     //
  1914.     //  now put the color that was there back.
  1915.     //
  1916.     if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  1917.     {
  1918.         SetPixel(hdc, 0, 0, rgbT);
  1919.         pdds->ReleaseDC(hdc);
  1920.     }
  1921.  
  1922.     return dw;
  1923. }
  1924. // MWH this funtion only work when there is directDraw support.  It use the transColor for 
  1925. // transparent blt.     if releaseTempSurf == FALSE.  It is caller's responsibility to release
  1926. // the surf.
  1927. BOOL CDCCX::TransparentBlt(int dx,
  1928.                             int dy,
  1929.                             int dw,
  1930.                             int dh,
  1931.                             int sx,
  1932.                             int sy,
  1933.                             int sw,
  1934.                             int sh,
  1935.                             NI_Pixmap *image,
  1936.                             COLORREF transColor,
  1937.                             LPDIRECTDRAWSURFACE surf)
  1938. {
  1939.     if (!GetPrimarySurface()) return FALSE;
  1940.     LPDDSURFACEDESC    ddesc = GetSurfDesc();
  1941.  
  1942.     RECT rect;
  1943.     HRESULT err = 1;
  1944.     rect.left = rect.top = 0;
  1945.     rect.bottom = dy + dh;
  1946.     rect.right = dx + dw;
  1947.     BOOL needRelease = TRUE;
  1948.     LPDIRECTDRAWSURFACE tempsurf;
  1949.     if (!surf) {
  1950.         tempsurf = CreateOffscreenSurface(rect);
  1951.     }
  1952.     else {
  1953.         tempsurf = surf;
  1954.         needRelease = FALSE;
  1955.     }
  1956.     HDC tempDC;
  1957.     FEBitmapInfo *imageInfo;
  1958.     imageInfo = (FEBitmapInfo*) image->client_data;
  1959.     if (tempsurf) {
  1960.         tempsurf->GetDC(&tempDC);
  1961.         ::StretchDIBits(tempDC,
  1962.                     CASTINT(dx), CASTINT(dy), 
  1963.                     CASTINT(dw), CASTINT(dh), 
  1964.                     CASTINT(sx), CASTINT(sy), 
  1965.                     CASTINT(sw), CASTINT(sh), 
  1966.                     image->bits,
  1967.                     imageInfo->bmpInfo,
  1968.                     DIB_RGB_COLORS,
  1969.                     SRCCOPY);
  1970.         ReleaseOffscreenSurfDC();
  1971.  
  1972.         rect.left = dx;
  1973.         rect.top = dy;
  1974.         tempsurf->ReleaseDC(tempDC);
  1975.         DDCOLORKEY  colorKey;
  1976.         if (ddesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { //palette device
  1977.             colorKey.dwColorSpaceLowValue = ::GetNearestPaletteIndex(GetPalette(), transColor);
  1978.             colorKey.dwColorSpaceHighValue = ::GetNearestPaletteIndex(GetPalette(), transColor);
  1979.         }
  1980.         else {
  1981.             colorKey.dwColorSpaceLowValue = DDColorMatch(tempsurf, transColor);
  1982.             colorKey.dwColorSpaceHighValue = DDColorMatch(tempsurf, transColor);
  1983.         }
  1984.         tempsurf->SetColorKey(DDCKEY_SRCBLT, &colorKey);
  1985.         err = GetBackSurface()->Blt(&rect, tempsurf, &rect, DDBLT_KEYSRC , NULL);
  1986.         if (err == DDERR_SURFACELOST) {
  1987.             RestoreAllDrawSurface();
  1988.             err = GetBackSurface()->Blt(&rect, tempsurf, &rect, DDBLT_KEYSRC , NULL);
  1989.         }
  1990.         if (needRelease) {
  1991.             tempsurf->Release();
  1992.         }
  1993.         LockOffscreenSurfDC();
  1994.     }
  1995.     if (err != 0) return FALSE;
  1996.     else
  1997.         return TRUE;
  1998. }
  1999. #endif
  2000.  
  2001. #define ROUNDUP(_x,_toMultipleOf) (((_x)+(_toMultipleOf)-1)/(_toMultipleOf)*(_toMultipleOf))
  2002.  
  2003. void    CDCCX::TileImage(HDC hdc, LTRB& Rect, NI_Pixmap* image, NI_Pixmap* mask, int32 x, int32 y)
  2004. {
  2005.     int iMinTileWidth, iMinTileHeight, iTileWidth, iTileHeight;
  2006.     int iRectWidth, iRectHeight, iOrigWidth, iOrigHeight;
  2007.     HBITMAP pTmpImageBitmap = NULL, pTmpMaskBitmap = NULL, pSavedImageBitmap, pSavedMaskBitmap;
  2008.     HGDIOBJ pOldObj;
  2009.     FEBitmapInfo *imageInfo;
  2010.     FEBitmapInfo *maskInfo;
  2011.     imageInfo = (FEBitmapInfo*) image->client_data;
  2012.     int32 lDrawingOrgX, lDrawingOrgY;
  2013.     GetDrawingOrigin(&lDrawingOrgX, &lDrawingOrgY);
  2014.  
  2015.     // If we a backdrop image has been explicitly specified and
  2016.     // it is transparent, then don't use the NT brush feature,
  2017.     // since it doesn't support masks.
  2018.     if ((!mask) && (imageInfo->hBitmap) && (CanCreateBrush(imageInfo->hBitmap, m_iBitsPerPixel))) {
  2019.         CPoint    brushOrg(CASTINT(lDrawingOrgX - m_lOrgX), CASTINT(lDrawingOrgY - m_lOrgY));
  2020.         HBRUSH    hBrush = CreatePatternBrush(imageInfo->hBitmap);
  2021.         ASSERT(hBrush);
  2022.  
  2023.         // We need to align the brush properly. The values to SetBrushOrg() specifiy
  2024.         // where the brush origin (i.e. the point (0, 0) of the brush) will be mapped.
  2025.         // The coordinates must be in device units
  2026.         ::LPtoDP(hdc, &brushOrg, 1);
  2027.         brushOrg.x %= (imageInfo->width * GetXConvertUnit());
  2028.         brushOrg.y %= (imageInfo->height * GetYConvertUnit());
  2029.         POINT tempPoint;
  2030. #ifdef _WIN32
  2031.         ::SetBrushOrgEx(hdc,brushOrg.x, brushOrg.y, &tempPoint);
  2032. #else
  2033.         ::SetBrushOrg( hdc, brushOrg.x, brushOrg.y );
  2034. #endif
  2035.         // Erase the background
  2036.         ::FillRect(hdc, (RECT*)&Rect, hBrush);
  2037.         VERIFY(::DeleteObject(hBrush));
  2038.  
  2039. #ifdef _WIN32
  2040.         // Restore the brush origin
  2041.         ::SetBrushOrgEx(hdc, tempPoint.x, tempPoint.y, NULL);
  2042. #endif
  2043.         ReleaseContextDC(hdc);
  2044.         return;
  2045.     }
  2046.  
  2047.     if (mask) {
  2048.         maskInfo = (FEBitmapInfo*) mask->client_data;
  2049.     }
  2050.  
  2051.     // If the width (or height) of the image is less than the smaller of
  2052.     // 32 and half the width (or height) of the area to be tiled, then tile the
  2053.     // image into a larger temporary bitmap and use the temporary bitmap
  2054.     // as the tile.     We also limit the actual area of the temporary tile to 4096.
  2055.     iOrigWidth = imageInfo->width * GetXConvertUnit();
  2056.     iOrigHeight = imageInfo->height *GetYConvertUnit();
  2057.     iRectWidth = Rect.right - Rect.left;
  2058.     iRectHeight = Rect.bottom - Rect.top;
  2059.     iMinTileWidth = MIN(32,MAX(iRectWidth/2,1));        // Tile must be at least this wide.
  2060.     iMinTileHeight = MIN(32,MAX(iRectHeight/2,1));        // Tile must be at least this high.
  2061.     iTileWidth = ROUNDUP(iMinTileWidth, iOrigWidth);    // Actual width of temporary tile.
  2062.     iTileHeight = ROUNDUP(iMinTileHeight, iOrigHeight);    // Actual height of temporary tile.
  2063.  
  2064.     if ((iOrigWidth < iMinTileWidth || iOrigHeight < iMinTileHeight) &&
  2065.         (iTileWidth * iTileHeight < 4096)) {
  2066.         HDC pTmpDC = NULL;
  2067.  
  2068.         // Create a temporary larger tile and use it instead of the original tile.
  2069.         HDC hhDC = GetContextDC();
  2070.         pTmpDC = CreateCompatibleDC(hhDC);
  2071.         ReleaseContextDC(hhDC);
  2072.         if (!pTmpDC)
  2073.             return;
  2074.         HPALETTE  hOldPal;
  2075.         if (m_bUseDibPalColors)
  2076.             hOldPal = ::SelectPalette(pTmpDC, GetPalette(), FALSE);
  2077.         pTmpImageBitmap = CreateLargerTile(hhDC, pTmpDC, m_pImageDC,
  2078.                                            image, m_bUseDibPalColors,
  2079.                                            iOrigWidth, iOrigHeight,
  2080.                                            iTileWidth, iTileHeight);
  2081.         if (!pTmpImageBitmap) { // OOM
  2082.             if (m_bUseDibPalColors)
  2083.                 ::SelectPalette(pTmpDC, hOldPal, FALSE);
  2084.             VERIFY(::DeleteDC(pTmpDC));
  2085.             return;
  2086.         }
  2087.         if (mask) {
  2088.             pTmpMaskBitmap = CreateLargerTile(hhDC, pTmpDC, m_pImageDC,
  2089.                                               mask, m_bUseDibPalColors,
  2090.                                               iOrigWidth, iOrigHeight,
  2091.                                               iTileWidth, iTileHeight);
  2092.             if (!pTmpMaskBitmap) { // OOM
  2093.                 if (m_bUseDibPalColors)
  2094.                     ::SelectPalette(pTmpDC, hOldPal, FALSE);
  2095.                 VERIFY(::DeleteDC(pTmpDC));
  2096.                 VERIFY(::DeleteObject(pTmpImageBitmap));
  2097.                 return;
  2098.             }
  2099.         }
  2100.         pSavedImageBitmap = imageInfo->hBitmap;
  2101.         imageInfo->hBitmap = pTmpImageBitmap;
  2102.         imageInfo->width = iTileWidth;
  2103.         imageInfo->height = iTileHeight;
  2104.         if (mask) {
  2105.             pSavedMaskBitmap = maskInfo->hBitmap;
  2106.             maskInfo->hBitmap = pTmpMaskBitmap;
  2107.             maskInfo->width = iTileWidth;
  2108.             maskInfo->height = iTileHeight;
  2109.         }
  2110.  
  2111.         if (m_bUseDibPalColors)
  2112.             ::SelectPalette(pTmpDC, hOldPal, FALSE);
  2113.         VERIFY(::DeleteDC(pTmpDC));
  2114.     }
  2115.  
  2116.     // Set a flag to indicate that we are in the tiling code.
  2117.     imageInfo->IsTile = TRUE;
  2118.     if (mask)
  2119.         maskInfo->IsTile = TRUE;
  2120.  
  2121.     // If we are going to call StretchPixmap, avoid selecting the image bitmap
  2122.     // into the memory DC each time.
  2123.     if (!mask && imageInfo->hBitmap)
  2124.         pOldObj = ::SelectObject(m_pImageDC, imageInfo->hBitmap);
  2125.     // We need to properly align the backdrop vertically (in logical units)
  2126.     int    srcY = CASTINT((((Rect.top - GetTopMargin())/ GetYConvertUnit()) - lDrawingOrgY + m_lOrgY ) % (imageInfo->height));
  2127.     int dstHeight = CASTINT((imageInfo->height* GetYConvertUnit()) - (srcY  * GetYConvertUnit()));
  2128.  
  2129.     // MWH -- this loop needs a rewrite.  I just do this for first pass on win16 compiler.
  2130.     // Should not check for the which Blt we want to use inside the loop.
  2131.     // Redraw the backdrop from left to right and top to bottom
  2132.     for (int currentY = CASTINT(Rect.top); currentY < CASTINT(Rect.bottom);) {
  2133.         // We need to properly align the backdrop horizontally (in logical units)
  2134.         int    srcX = CASTINT((((Rect.left - GetLeftMargin()) / GetXConvertUnit()) - lDrawingOrgX + m_lOrgX)% (imageInfo->width));
  2135.         int    dstWidth = CASTINT((imageInfo->width * GetXConvertUnit()) - srcX * GetXConvertUnit());
  2136.  
  2137.         // Only draw as far down as we've been asked to draw
  2138.         if (CASTINT(currentY + dstHeight) > CASTINT(Rect.bottom))
  2139.             dstHeight = CASTINT(Rect.bottom - currentY);
  2140.  
  2141.     
  2142.         // Loop across the row
  2143.         for (int currentX = CASTINT(Rect.left); currentX < CASTINT(Rect.right);) {
  2144.             // Only draw as far across as we've been asked to draw
  2145.             if (currentX + dstWidth > Rect.right)
  2146.                 dstWidth = CASTINT(Rect.right - currentX);
  2147.  
  2148.             // m_pImageDC is in device space, so we need to convert coordinates
  2149.             RECT    srcRect;
  2150.             ::SetRect(&srcRect, srcX, srcY, srcX + (dstWidth/ GetXConvertUnit()), srcY + (dstHeight/ GetYConvertUnit()));
  2151.             if (mask) {
  2152.                 if (imageInfo->hBitmap && maskInfo->hBitmap) {
  2153. #ifdef _WIN32
  2154.                     if (sysInfo.m_bWinNT && (GetContextType() != MetaFile)) {
  2155.                         HBITMAP hOldBitmap = (HBITMAP)::SelectObject(m_pImageDC, imageInfo->hBitmap);
  2156. #ifdef USE_DIB_SECTION
  2157.                         if (image->bits)
  2158.                             MaskBlt(hdc, 
  2159.                                 currentX, currentY, 
  2160.                                 dstWidth, 
  2161.                                 dstHeight,
  2162.                                 m_pImageDC, srcRect.left, srcRect.top,
  2163.                                 maskInfo->hBitmap,
  2164.                                 srcRect.left, srcRect.top,
  2165.                                 MAKEROP4(SRCCOPY, 0x00AA0029));  // 0x00AA0029 is destination...
  2166.                         else
  2167. #endif
  2168.                             MaskBlt(hdc, 
  2169.                                 currentX, currentY, 
  2170.                                 dstWidth, 
  2171.                                 dstHeight,
  2172.                                 m_pImageDC, srcRect.left, srcRect.top,
  2173.                                 maskInfo->hBitmap,
  2174.                                 srcRect.left, srcRect.top,
  2175.                                 MAKEROP4(0x00AA0029, SRCCOPY));  // 0x00AA0029 is destination...
  2176.                         ::SelectObject(m_pImageDC, hOldBitmap);
  2177.                     }
  2178.                     else
  2179. #endif
  2180.                         StretchMaskBlt(hdc, 
  2181.                                 imageInfo->hBitmap, maskInfo->hBitmap,
  2182.                                 currentX, currentY, 
  2183.                                 dstWidth, 
  2184.                                 dstHeight,
  2185.                                 srcRect.left, srcRect.top, 
  2186.                                 srcRect.right - srcRect.left, 
  2187.                                 srcRect.bottom - srcRect.top); 
  2188.                 }
  2189.                 else {    // blt bitmap with mask.
  2190.                     _StretchDIBitsWithMask(hdc,
  2191.                                     currentX,     currentY,
  2192.                                     dstWidth, 
  2193.                                     dstHeight,
  2194.                                     srcRect.left,
  2195.                                     // the reason for this calculation is that Window's bitmap
  2196.                                     // is reverse.  The first scan line will be at the bottom of
  2197.                                     // the bitmap buffer.
  2198.                                     imageInfo->height - srcRect.bottom,
  2199.                                     srcRect.right - srcRect.left,
  2200.                                     srcRect.bottom - srcRect.top,
  2201.                                     image,
  2202.                                     mask);
  2203.                 }
  2204.  
  2205.             }
  2206.             else {
  2207.                 StretchPixmap(hdc, image,
  2208.                                 currentX, currentY, 
  2209.                                 dstWidth, 
  2210.                                 dstHeight,
  2211.                                 srcRect.left, srcRect.top, 
  2212.                                 srcRect.right - srcRect.left, 
  2213.                                 srcRect.bottom - srcRect.top);
  2214.  
  2215.             }
  2216.  
  2217.             currentX += dstWidth;
  2218.             srcX = 0;
  2219.             dstWidth = imageInfo->width * GetXConvertUnit();
  2220.         }
  2221.  
  2222.         currentY += dstHeight;
  2223.         srcY = 0;
  2224.         dstHeight = imageInfo->height  * GetYConvertUnit();
  2225.     }
  2226.     // If we called StretchPixmap, restore the memory DC to its previous state.
  2227.     if (!mask && imageInfo->hBitmap)
  2228.         ::SelectObject(m_pImageDC, pOldObj);
  2229.  
  2230.     // If we created a temporary tile, then restore the original bitmaps.
  2231.     if (pTmpImageBitmap) {
  2232.         imageInfo->width = iOrigWidth;
  2233.         imageInfo->height = iOrigHeight;
  2234.         imageInfo->hBitmap = pSavedImageBitmap;
  2235.         VERIFY(::DeleteObject(pTmpImageBitmap));
  2236.     }
  2237.     if (pTmpMaskBitmap) {
  2238.         maskInfo->width = iOrigWidth;
  2239.         maskInfo->height = iOrigHeight;
  2240.         maskInfo->hBitmap = pSavedMaskBitmap;
  2241.         VERIFY(::DeleteObject(pTmpMaskBitmap));
  2242.     }
  2243.  
  2244.     // Reset the flags to indicate that we are done tiling.
  2245.     imageInfo->IsTile = FALSE;
  2246.     if (mask)
  2247.         maskInfo->IsTile = FALSE;
  2248. }
  2249.  
  2250.  
  2251.