home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / drawable.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  15.2 KB  |  561 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. //   drawable.cpp - Classes used for maintaining the notion of 
  20. //                  offscreen and onscreen drawables, so that 
  21. //                  document contents can be drawn to either
  22. //                  location. Currently used for LAYERS.
  23.  
  24. #include "stdafx.h"
  25.  
  26. #ifdef LAYERS
  27. #include "drawable.h"
  28. #include "xp_rect.h"
  29. #include "cxprint.h"
  30.  
  31. // In this implementation, we only have a single offscreen drawable,
  32. // and all its state is stored in the following statics:
  33. HDC COffscreenDrawable::m_hDC = 0;
  34. HPALETTE COffscreenDrawable::m_hSelectedPalette = 0;
  35. COffscreenDrawable *COffscreenDrawable::m_pOffscreenDrawable = NULL;
  36. HBITMAP COffscreenDrawable::m_hBitmap = 0;
  37. CL_Drawable * COffscreenDrawable::m_pOwner = NULL;
  38. int32 COffscreenDrawable::m_lWidth = 0;
  39. int32 COffscreenDrawable::m_lHeight = 0;
  40. UINT COffscreenDrawable::m_uRefCnt = 0;
  41.  
  42. // CDrawable base class
  43. CDrawable::CDrawable() 
  44. {
  45.     m_lOrgX = m_lOrgY = 0;
  46.     m_hClipRgn = FE_NULL_REGION;
  47.     m_parentContext = NULL;
  48. }
  49. CDrawable::CDrawable(CAbstractCX*    parentContext) 
  50. {
  51.     m_lOrgX = m_lOrgY = 0;
  52.     m_hClipRgn = FE_NULL_REGION;
  53.     m_parentContext = parentContext;
  54. }
  55.  
  56. // Set and get the origin of the drawable 
  57. void 
  58. CDrawable::SetOrigin(int32 lOrgX, int32 lOrgY)
  59. {
  60.     m_lOrgX = lOrgX;
  61.     m_lOrgY = lOrgY;
  62. }
  63.  
  64. void 
  65. CDrawable::GetOrigin(int32 *lOrgX, int32 *lOrgY)
  66. {
  67.     *lOrgX = m_lOrgX;
  68.     *lOrgY = m_lOrgY;
  69. }
  70.  
  71. // Set the clip region of the drawable.
  72. void 
  73. CDrawable::SetClip(FE_Region hClipRgn)
  74. {
  75.     HDC hDC = GetDrawableDC();
  76.     ASSERT(hDC);
  77.     if (hDC) {
  78.         if (hClipRgn == FE_NULL_REGION)
  79.             ::SelectClipRgn(hDC, NULL);
  80.         else
  81.             ::SelectClipRgn(hDC, FE_GetMDRegion(hClipRgn));
  82.             m_hClipRgn = hClipRgn;
  83.     }
  84.     ReleaseDrawableDC(hDC);
  85. }
  86.  
  87. typedef struct fe_CopyRectStruct {
  88.     HDC hSrcDC;
  89.     HDC hDstDC;
  90.     CAbstractCX*    m_parentContext;
  91. } fe_CopyRectStruct;
  92.  
  93. // For copying pixels, we draw a rectangle at a time
  94. static void
  95. fe_copy_rect_func(void *pRectStruct, XP_Rect *pRect)
  96. {
  97. #ifdef DDRAW    
  98.     CAbstractCX* m_parentContext = ((fe_CopyRectStruct *)pRectStruct)->m_parentContext;
  99.     if (m_parentContext && m_parentContext->IsWindowContext()) {
  100.         CWinCX* pWinCX =  (CWinCX*)m_parentContext;
  101.         if ( pWinCX->GetPrimarySurface()) {
  102.             LTRB rect;
  103.             rect.left = pRect->left;
  104.             rect.top = pRect->top;
  105.             rect.right = pRect->right;
  106.             rect.bottom = pRect->bottom;
  107.             pWinCX->BltToScreen(rect);
  108.             return;
  109.         }
  110.     }
  111.      
  112. #endif
  113.     HDC hSrcDC = ((fe_CopyRectStruct *)pRectStruct)->hSrcDC;
  114.     HDC hDstDC = ((fe_CopyRectStruct *)pRectStruct)->hDstDC;
  115.  
  116.     BitBlt(hDstDC, CASTINT(pRect->left), CASTINT(pRect->top), 
  117.            CASTINT(pRect->right-pRect->left),
  118.            CASTINT(pRect->bottom-pRect->top),
  119.            hSrcDC,
  120.            CASTINT(pRect->left), CASTINT(pRect->top),
  121.            SRCCOPY);
  122. }
  123.  
  124. void
  125. CDrawable::CopyPixels(CDrawable *pSrcDrawable, FE_Region hCopyRgn)
  126. {
  127.     HDC hSrcDC;
  128.     HDC hDstDC = GetDrawableDC();
  129.     fe_CopyRectStruct rectStruct;
  130.  
  131.     ASSERT(hDstDC);
  132.     
  133.     if (hDstDC && pSrcDrawable && (hCopyRgn != FE_NULL_REGION)) {
  134.         hSrcDC = pSrcDrawable->GetDrawableDC();
  135.  
  136.         if (hSrcDC) {
  137.     #ifndef XP_WIN32
  138.                 // On Win16, we must BLT through the clip, instead of iterating
  139.                 // through the region's rectangles, due to Win16's inability
  140.                 // to decompose a region into its component rectangles.
  141.                 SetClip(hCopyRgn);
  142.     #endif
  143.             rectStruct.hDstDC = hDstDC;
  144.             rectStruct.hSrcDC = hSrcDC;
  145.             rectStruct.m_parentContext = m_parentContext;
  146.                 // The following statement is misleading, because on
  147.                 // Win16, FE_ForEachRectInRegion() calls its client
  148.                 // function only once, using the bounding box of the
  149.                 // region, not with each individual rectangle in the
  150.                 // region.
  151.             FE_ForEachRectInRegion(hCopyRgn, 
  152.                        (FE_RectInRegionFunc)fe_copy_rect_func,
  153.                        (void *)&rectStruct);
  154.     #ifndef XP_WIN32
  155.                 SetClip(NULL);
  156.     #endif
  157.  
  158.             ReleaseDrawableDC(hSrcDC);
  159.         }
  160.         ReleaseDrawableDC(hDstDC);
  161.     }
  162. }
  163.  
  164.  
  165. COnscreenDrawable::COnscreenDrawable(HDC hDC, CAbstractCX* parentContext)
  166. :CDrawable(parentContext)
  167. {
  168.     m_hDC = hDC;
  169. }
  170.  
  171. CPrinterDrawable::CPrinterDrawable(HDC hDC, 
  172.                                    int32 lLeftMargin, 
  173.                                    int32 lRightMargin,
  174.                                    int32 lTopMargin,
  175.                                    int32 lBottomMargin,
  176.                                    CAbstractCX* parentContext)
  177. {
  178.     m_hDC = hDC;
  179.     m_lLeftMargin = lLeftMargin;
  180.     m_lRightMargin = lRightMargin;
  181.     m_lTopMargin = lTopMargin;
  182.     m_lBottomMargin = lBottomMargin;
  183.     m_parentContext = parentContext;
  184. }
  185.  
  186. void 
  187. CPrinterDrawable::SetClip(FE_Region hClipRgn)
  188. {
  189.     XP_Rect bbox;
  190.  
  191.     if (hClipRgn != FE_NULL_REGION) {
  192.         FE_Region hTempClipRgn;
  193.         RECT rect;
  194.         
  195.         /* Get region bounding box and add in the margins */
  196.         FE_GetRegionBoundingBox(hClipRgn, &bbox);
  197.         XP_OffsetRect(&bbox, m_lLeftMargin, m_lTopMargin);
  198.  
  199.         rect.left = bbox.left;
  200.         rect.right = bbox.right;
  201.         rect.top = bbox.top;
  202.         rect.bottom = bbox.bottom;
  203.         
  204.         ::LPtoDP(m_hDC, (LPPOINT)&rect, 2);
  205.         
  206.         bbox.left = rect.left;
  207.         bbox.right = rect.right;
  208.         bbox.top = rect.top;
  209.         bbox.bottom = rect.bottom;
  210.  
  211.         /* 
  212.          * Create, set and then destroy a region based on the offset and
  213.          * scaled bounding box.
  214.          */
  215.         hTempClipRgn = FE_CreateRectRegion(&bbox);
  216.         
  217.         CDrawable::SetClip(hTempClipRgn);
  218.         if (hTempClipRgn)
  219.             FE_DestroyRegion(hTempClipRgn);
  220. #ifdef XP_WIN32        
  221.         CPrintCX* pContext = (CPrintCX*)m_parentContext;
  222.         HDC m_offscrnDC = pContext->GetOffscreenDC();
  223.  
  224.         if (m_offscrnDC) {
  225.             FE_GetRegionBoundingBox(hClipRgn, &bbox);
  226.             CPrintCX* prntContext = (CPrintCX*)m_parentContext;
  227.             bbox.left = (bbox.left +prntContext->GetXConvertUnit())/ prntContext->GetXConvertUnit();
  228.             bbox.right = (bbox.right +prntContext->GetYConvertUnit())/ prntContext->GetXConvertUnit();
  229.             bbox.top = (bbox.top + prntContext->GetXConvertUnit())/ prntContext->GetYConvertUnit();
  230.             bbox.bottom = (bbox.bottom + prntContext->GetYConvertUnit()) / prntContext->GetYConvertUnit();
  231.             hTempClipRgn = FE_CreateRectRegion(&bbox);
  232.             if (hTempClipRgn == FE_NULL_REGION)
  233.                 ::SelectClipRgn(m_offscrnDC, NULL);
  234.             else
  235.                 ::SelectClipRgn(m_offscrnDC, FE_GetMDRegion(hTempClipRgn));
  236.             if (hTempClipRgn)
  237.                 FE_DestroyRegion(hTempClipRgn);
  238.         }
  239. #endif        
  240.     }
  241.     else
  242.         CDrawable::SetClip(FE_NULL_REGION);
  243. }
  244.  
  245.  
  246. // We should get rid of this function, since it does nothing
  247. // that the new operator does not.
  248. COffscreenDrawable *
  249. COffscreenDrawable::AllocateOffscreen(HDC hParentDC, HPALETTE hPal, CAbstractCX* parentContext)
  250. {
  251.     return new COffscreenDrawable(hParentDC, hPal, parentContext);
  252. }
  253.  
  254. COffscreenDrawable::COffscreenDrawable(HDC hParentDC, HPALETTE hPal, CAbstractCX* parentContext)
  255. :CDrawable(parentContext)
  256. {
  257.     m_hParentDC = hParentDC;
  258.     m_hSaveBitmap = NULL;
  259.     m_hSavePalette = NULL;
  260.     m_hParentPal = hPal;
  261.     m_parentContext = parentContext;
  262. }
  263. // Set the clip region of the drawable.
  264. void 
  265. COffscreenDrawable::SetClip(FE_Region hClipRgn)
  266. {
  267. #ifdef DDRAW
  268.     if (m_parentContext && m_parentContext->IsWindowContext()){
  269.         CWinCX *pwincx = (CWinCX*)m_parentContext;
  270.         if (pwincx->GetBackSurface()) {
  271.             pwincx->SetClipOnDrawSurface(pwincx->GetBackSurface(), FE_GetMDRegion(hClipRgn));
  272.         }
  273.     }
  274.     else 
  275.         CDrawable::SetClip(hClipRgn);
  276. #else
  277.     CDrawable::SetClip(hClipRgn);
  278. #endif
  279.     m_hClipRgn = hClipRgn;
  280. }
  281. HDC COffscreenDrawable::GetDrawableDC()
  282. {
  283.     if (m_hDC) 
  284.         return m_hDC;
  285.     else {    // we must be using DirectDraw's offscreen surface.
  286.         CWinCX *pwincx = (CWinCX*)m_parentContext;
  287.  
  288.         return pwincx->GetDispDC();
  289.     }
  290. }
  291. void COffscreenDrawable::ReleaseDrawableDC(HDC hdc) 
  292. {
  293. }
  294.  
  295. // Get rid of any offscreen constructs if they exist
  296. void
  297. COffscreenDrawable::delete_offscreen()
  298. {
  299.     if (m_hDC) {
  300.     ::SelectObject(m_hDC, m_hSaveBitmap);
  301.         ::SelectPalette(m_hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
  302.         m_hSelectedPalette = 0;
  303.     DeleteDC(m_hDC);
  304.     }
  305.  
  306.     if (m_hBitmap) 
  307.        ::DeleteObject(m_hBitmap);
  308.     
  309.     m_hDC = NULL;
  310.     m_hSaveBitmap = NULL;
  311.     m_hSavePalette = NULL;
  312.     m_hBitmap = NULL;
  313.     m_lWidth = m_lHeight = 0;
  314. }
  315.  
  316. COffscreenDrawable::~COffscreenDrawable()
  317. {
  318.     // It's possible that the window that "owns" this offscreen
  319.     // drawable is about to be deleted, along with its palette.  We
  320.     // have to deselect the palette from this drawable's DC so that
  321.     // it can be safely deleted.
  322.     if (m_hSelectedPalette && (m_hParentPal == m_hSelectedPalette)) {
  323.         ::SelectPalette(m_hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
  324.         m_hSelectedPalette = 0;
  325.     }
  326. }
  327.  
  328. void 
  329. COffscreenDrawable::InitDrawable(CL_Drawable *pCLDrawable)
  330. {
  331.     m_uRefCnt++;
  332. }
  333.  
  334. void 
  335. COffscreenDrawable::RelinquishDrawable(CL_Drawable *pCLDrawable)
  336. {
  337.     ASSERT(m_uRefCnt > 0);
  338.  
  339.     if (m_uRefCnt)
  340.         m_uRefCnt--;
  341.  
  342.     // There are no clients left. Let's get rid of the offscreen
  343.     // bitmap.
  344.     if (m_uRefCnt == 0)
  345.     delete_offscreen();
  346. }
  347.  
  348. // Called before using the drawable.
  349. PRBool 
  350. COffscreenDrawable::LockDrawable(CL_Drawable *pCLDrawable, 
  351.                  CL_DrawableState newState)
  352. {
  353.  
  354.     if (newState == CL_UNLOCK_DRAWABLE)
  355.         return PR_TRUE;
  356.  
  357.     CWinCX* pWinCX =  (CWinCX*)m_parentContext;
  358. #ifdef DDRAW
  359.     if (!pWinCX->GetBackSurface() && !m_hBitmap)
  360.         return PR_FALSE;
  361. #else
  362.     if (!m_hBitmap)
  363.         return PR_FALSE;
  364. #endif    
  365.     /* 
  366.      * Check to see if this CL_Drawable was the last one to use
  367.      * this drawable. If not, someone else might have modified
  368.      * the bits since the last time this CL_Drawable wrote to
  369.      * to them.
  370.      */
  371.     if ((newState & CL_LOCK_DRAWABLE_FOR_READ) &&
  372.     (m_pOwner != pCLDrawable))
  373.         return PR_FALSE;
  374.  
  375.     m_pOwner = pCLDrawable;
  376.  
  377.     //mwh - If we are using directDraw, don't do the palette stuff..
  378.     // If the last user of this drawable relinquished it, then 
  379.     // we need to select the new user's palette into the DC.
  380. #ifdef DDRAW
  381.     if (!(pWinCX->GetBackSurface()) && !m_hSelectedPalette && m_hParentPal) {
  382. #else
  383.     if (!m_hSelectedPalette && m_hParentPal) {
  384. #endif
  385.         ::SelectPalette(m_hDC, m_hParentPal, FALSE);
  386.         m_hSelectedPalette = m_hParentPal;
  387.     }
  388.         
  389.     return PR_TRUE;
  390. }
  391.  
  392. // Set the required dimensions of the drawable. 
  393. void 
  394. COffscreenDrawable::SetDimensions(int32 lWidth, int32 lHeight)
  395. {
  396.  
  397.     if ((lWidth > m_lWidth) || (lHeight > m_lHeight)) {
  398.     
  399.     /* 
  400.      * If there is only one client of the backing store,
  401.      * we can resize it to the dimensions specified.
  402.      * Otherwise, we can make it larger, but not smaller
  403.      */
  404.     if (m_uRefCnt > 1) {
  405.         if (lWidth < m_lWidth)
  406.             lWidth = m_lWidth;
  407.         if (lHeight < m_lHeight)
  408.             lHeight = m_lHeight;
  409.     }
  410.  
  411.     /* If we already have a bitmap, get rid of it */
  412.     if (m_hBitmap && m_hDC) {
  413.         ::SelectObject(m_hDC, m_hSaveBitmap);
  414.         ::DeleteObject(m_hBitmap);
  415.         m_hBitmap = NULL;
  416.     }
  417.     CWinCX* pWinCX =  (CWinCX*)m_parentContext;
  418.  
  419.     //mwh - If we are using directDraw, don't create a compatible DC here.
  420. #ifdef DDRAW
  421.     if (!(pWinCX->GetBackSurface())) {
  422. #endif
  423.         if (!m_hDC) {
  424.                 m_hDC = ::CreateCompatibleDC(m_hParentDC); 
  425.                 if (!m_hDC)
  426.                     return;
  427.             
  428.             SetPalette(m_hParentPal);
  429.             ::SetBkMode(m_hDC, TRANSPARENT);
  430.         }
  431.  
  432.         m_hBitmap = ::CreateCompatibleBitmap(m_hParentDC,
  433.                                              CASTINT(lWidth), CASTINT(lHeight));
  434.             if (!m_hBitmap) {
  435.                 /* 
  436.                  * If the bitmap allocation failed, we just delete all offscreen
  437.                  * resources and fail locking and hence, go fall back to
  438.                  * onscreen drawing.
  439.                  */
  440.                 delete_offscreen();
  441.             }
  442.         m_hSaveBitmap = (HBITMAP)::SelectObject(m_hDC, m_hBitmap);
  443. #ifdef DDRAW
  444.     }
  445. #endif
  446.     m_lWidth = lWidth;
  447.     m_lHeight = lHeight;
  448.     }
  449. }
  450.  
  451. void
  452. COffscreenDrawable::SetPalette(HPALETTE hPal)
  453. {
  454.     CWinCX* pWinCX =  (CWinCX*)m_parentContext;
  455. #ifdef DDRAW
  456.     if (!(pWinCX->GetBackSurface())) {
  457. #endif
  458.         HPALETTE hOldPalette = NULL;
  459.     
  460.         if(hPal && m_hDC)    {
  461.             hOldPalette = ::SelectPalette(m_hDC, hPal, FALSE);
  462.             // don't realize palette with memory DC.
  463.                 m_hSelectedPalette = hPal;
  464.         }
  465.         
  466.         if (!m_hSavePalette)
  467.             m_hSavePalette = hOldPalette;
  468.         m_hParentPal = hPal;
  469. #ifdef DDRAW
  470.     }
  471. #endif
  472. }
  473.  
  474. PRBool
  475. fe_lock_drawable(CL_Drawable *drawable, CL_DrawableState state)
  476. {
  477.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  478.  
  479.     return pDrawable->LockDrawable(drawable, state);
  480. }
  481.  
  482. void
  483. fe_init_drawable(CL_Drawable *drawable)
  484. {
  485.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  486.     
  487.     pDrawable->InitDrawable(drawable);
  488. }
  489.  
  490. void
  491. fe_relinquish_drawable(CL_Drawable *drawable)
  492. {
  493.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  494.     
  495.     pDrawable->RelinquishDrawable(drawable);
  496. }
  497.  
  498. void
  499. fe_set_drawable_origin(CL_Drawable *drawable, int32 lOrgX, int32 lOrgY)
  500. {
  501.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  502.     
  503.     pDrawable->SetOrigin(lOrgX, lOrgY);
  504. }
  505.  
  506. void
  507. fe_get_drawable_origin(CL_Drawable *drawable, int32 *plOrgX, int32 *plOrgY)
  508. {
  509.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  510.     
  511.     pDrawable->GetOrigin(plOrgX, plOrgY);
  512. }
  513.  
  514. void
  515. fe_set_drawable_clip(CL_Drawable *drawable, FE_Region hClipRgn)
  516. {
  517.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  518.  
  519.     pDrawable->SetClip(hClipRgn);
  520. }
  521.  
  522. void
  523. fe_restore_drawable_clip(CL_Drawable *drawable)
  524. {
  525.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  526.  
  527.     pDrawable->SetClip(NULL);
  528. }
  529.  
  530. void
  531. fe_copy_pixel(CL_Drawable *pSrc, CL_Drawable *pDst, FE_Region hCopyRgn)
  532. {
  533.     CDrawable *pSrcDrawable = (CDrawable *)CL_GetDrawableClientData(pSrc);
  534.     CDrawable *pDstDrawable = (CDrawable *)CL_GetDrawableClientData(pDst);
  535.  
  536.     pDstDrawable->CopyPixels(pSrcDrawable, hCopyRgn);
  537. }
  538.  
  539. void
  540. fe_drawable_set_dimensions(CL_Drawable *drawable, uint32 lWidth, uint32 lHeight)
  541. {
  542.     CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
  543.  
  544.     pDrawable->SetDimensions(lWidth, lHeight);
  545. }
  546.  
  547. CL_DrawableVTable wfe_drawable_vtable = {
  548.     fe_lock_drawable,
  549.     fe_init_drawable,
  550.     fe_relinquish_drawable,
  551.     NULL,
  552.     fe_set_drawable_origin,
  553.     fe_get_drawable_origin,
  554.     fe_set_drawable_clip,
  555.     fe_restore_drawable_clip,
  556.     fe_copy_pixel,
  557.     fe_drawable_set_dimensions
  558. };
  559.  
  560. #endif // LAYERS
  561.