home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- // drawable.cpp - Classes used for maintaining the notion of
- // offscreen and onscreen drawables, so that
- // document contents can be drawn to either
- // location. Currently used for LAYERS.
-
- #include "stdafx.h"
-
- #ifdef LAYERS
- #include "drawable.h"
- #include "xp_rect.h"
- #include "cxprint.h"
-
- // In this implementation, we only have a single offscreen drawable,
- // and all its state is stored in the following statics:
- HDC COffscreenDrawable::m_hDC = 0;
- HPALETTE COffscreenDrawable::m_hSelectedPalette = 0;
- COffscreenDrawable *COffscreenDrawable::m_pOffscreenDrawable = NULL;
- HBITMAP COffscreenDrawable::m_hBitmap = 0;
- CL_Drawable * COffscreenDrawable::m_pOwner = NULL;
- int32 COffscreenDrawable::m_lWidth = 0;
- int32 COffscreenDrawable::m_lHeight = 0;
- UINT COffscreenDrawable::m_uRefCnt = 0;
-
- // CDrawable base class
- CDrawable::CDrawable()
- {
- m_lOrgX = m_lOrgY = 0;
- m_hClipRgn = FE_NULL_REGION;
- m_parentContext = NULL;
- }
- CDrawable::CDrawable(CAbstractCX* parentContext)
- {
- m_lOrgX = m_lOrgY = 0;
- m_hClipRgn = FE_NULL_REGION;
- m_parentContext = parentContext;
- }
-
- // Set and get the origin of the drawable
- void
- CDrawable::SetOrigin(int32 lOrgX, int32 lOrgY)
- {
- m_lOrgX = lOrgX;
- m_lOrgY = lOrgY;
- }
-
- void
- CDrawable::GetOrigin(int32 *lOrgX, int32 *lOrgY)
- {
- *lOrgX = m_lOrgX;
- *lOrgY = m_lOrgY;
- }
-
- // Set the clip region of the drawable.
- void
- CDrawable::SetClip(FE_Region hClipRgn)
- {
- HDC hDC = GetDrawableDC();
- ASSERT(hDC);
- if (hDC) {
- if (hClipRgn == FE_NULL_REGION)
- ::SelectClipRgn(hDC, NULL);
- else
- ::SelectClipRgn(hDC, FE_GetMDRegion(hClipRgn));
- m_hClipRgn = hClipRgn;
- }
- ReleaseDrawableDC(hDC);
- }
-
- typedef struct fe_CopyRectStruct {
- HDC hSrcDC;
- HDC hDstDC;
- CAbstractCX* m_parentContext;
- } fe_CopyRectStruct;
-
- // For copying pixels, we draw a rectangle at a time
- static void
- fe_copy_rect_func(void *pRectStruct, XP_Rect *pRect)
- {
- #ifdef DDRAW
- CAbstractCX* m_parentContext = ((fe_CopyRectStruct *)pRectStruct)->m_parentContext;
- if (m_parentContext && m_parentContext->IsWindowContext()) {
- CWinCX* pWinCX = (CWinCX*)m_parentContext;
- if ( pWinCX->GetPrimarySurface()) {
- LTRB rect;
- rect.left = pRect->left;
- rect.top = pRect->top;
- rect.right = pRect->right;
- rect.bottom = pRect->bottom;
- pWinCX->BltToScreen(rect);
- return;
- }
- }
-
- #endif
- HDC hSrcDC = ((fe_CopyRectStruct *)pRectStruct)->hSrcDC;
- HDC hDstDC = ((fe_CopyRectStruct *)pRectStruct)->hDstDC;
-
- BitBlt(hDstDC, CASTINT(pRect->left), CASTINT(pRect->top),
- CASTINT(pRect->right-pRect->left),
- CASTINT(pRect->bottom-pRect->top),
- hSrcDC,
- CASTINT(pRect->left), CASTINT(pRect->top),
- SRCCOPY);
- }
-
- void
- CDrawable::CopyPixels(CDrawable *pSrcDrawable, FE_Region hCopyRgn)
- {
- HDC hSrcDC;
- HDC hDstDC = GetDrawableDC();
- fe_CopyRectStruct rectStruct;
-
- ASSERT(hDstDC);
-
- if (hDstDC && pSrcDrawable && (hCopyRgn != FE_NULL_REGION)) {
- hSrcDC = pSrcDrawable->GetDrawableDC();
-
- if (hSrcDC) {
- #ifndef XP_WIN32
- // On Win16, we must BLT through the clip, instead of iterating
- // through the region's rectangles, due to Win16's inability
- // to decompose a region into its component rectangles.
- SetClip(hCopyRgn);
- #endif
- rectStruct.hDstDC = hDstDC;
- rectStruct.hSrcDC = hSrcDC;
- rectStruct.m_parentContext = m_parentContext;
- // The following statement is misleading, because on
- // Win16, FE_ForEachRectInRegion() calls its client
- // function only once, using the bounding box of the
- // region, not with each individual rectangle in the
- // region.
- FE_ForEachRectInRegion(hCopyRgn,
- (FE_RectInRegionFunc)fe_copy_rect_func,
- (void *)&rectStruct);
- #ifndef XP_WIN32
- SetClip(NULL);
- #endif
-
- ReleaseDrawableDC(hSrcDC);
- }
- ReleaseDrawableDC(hDstDC);
- }
- }
-
-
- COnscreenDrawable::COnscreenDrawable(HDC hDC, CAbstractCX* parentContext)
- :CDrawable(parentContext)
- {
- m_hDC = hDC;
- }
-
- CPrinterDrawable::CPrinterDrawable(HDC hDC,
- int32 lLeftMargin,
- int32 lRightMargin,
- int32 lTopMargin,
- int32 lBottomMargin,
- CAbstractCX* parentContext)
- {
- m_hDC = hDC;
- m_lLeftMargin = lLeftMargin;
- m_lRightMargin = lRightMargin;
- m_lTopMargin = lTopMargin;
- m_lBottomMargin = lBottomMargin;
- m_parentContext = parentContext;
- }
-
- void
- CPrinterDrawable::SetClip(FE_Region hClipRgn)
- {
- XP_Rect bbox;
-
- if (hClipRgn != FE_NULL_REGION) {
- FE_Region hTempClipRgn;
- RECT rect;
-
- /* Get region bounding box and add in the margins */
- FE_GetRegionBoundingBox(hClipRgn, &bbox);
- XP_OffsetRect(&bbox, m_lLeftMargin, m_lTopMargin);
-
- rect.left = bbox.left;
- rect.right = bbox.right;
- rect.top = bbox.top;
- rect.bottom = bbox.bottom;
-
- ::LPtoDP(m_hDC, (LPPOINT)&rect, 2);
-
- bbox.left = rect.left;
- bbox.right = rect.right;
- bbox.top = rect.top;
- bbox.bottom = rect.bottom;
-
- /*
- * Create, set and then destroy a region based on the offset and
- * scaled bounding box.
- */
- hTempClipRgn = FE_CreateRectRegion(&bbox);
-
- CDrawable::SetClip(hTempClipRgn);
- if (hTempClipRgn)
- FE_DestroyRegion(hTempClipRgn);
- #ifdef XP_WIN32
- CPrintCX* pContext = (CPrintCX*)m_parentContext;
- HDC m_offscrnDC = pContext->GetOffscreenDC();
-
- if (m_offscrnDC) {
- FE_GetRegionBoundingBox(hClipRgn, &bbox);
- CPrintCX* prntContext = (CPrintCX*)m_parentContext;
- bbox.left = (bbox.left +prntContext->GetXConvertUnit())/ prntContext->GetXConvertUnit();
- bbox.right = (bbox.right +prntContext->GetYConvertUnit())/ prntContext->GetXConvertUnit();
- bbox.top = (bbox.top + prntContext->GetXConvertUnit())/ prntContext->GetYConvertUnit();
- bbox.bottom = (bbox.bottom + prntContext->GetYConvertUnit()) / prntContext->GetYConvertUnit();
- hTempClipRgn = FE_CreateRectRegion(&bbox);
- if (hTempClipRgn == FE_NULL_REGION)
- ::SelectClipRgn(m_offscrnDC, NULL);
- else
- ::SelectClipRgn(m_offscrnDC, FE_GetMDRegion(hTempClipRgn));
- if (hTempClipRgn)
- FE_DestroyRegion(hTempClipRgn);
- }
- #endif
- }
- else
- CDrawable::SetClip(FE_NULL_REGION);
- }
-
-
- // We should get rid of this function, since it does nothing
- // that the new operator does not.
- COffscreenDrawable *
- COffscreenDrawable::AllocateOffscreen(HDC hParentDC, HPALETTE hPal, CAbstractCX* parentContext)
- {
- return new COffscreenDrawable(hParentDC, hPal, parentContext);
- }
-
- COffscreenDrawable::COffscreenDrawable(HDC hParentDC, HPALETTE hPal, CAbstractCX* parentContext)
- :CDrawable(parentContext)
- {
- m_hParentDC = hParentDC;
- m_hSaveBitmap = NULL;
- m_hSavePalette = NULL;
- m_hParentPal = hPal;
- m_parentContext = parentContext;
- }
- // Set the clip region of the drawable.
- void
- COffscreenDrawable::SetClip(FE_Region hClipRgn)
- {
- #ifdef DDRAW
- if (m_parentContext && m_parentContext->IsWindowContext()){
- CWinCX *pwincx = (CWinCX*)m_parentContext;
- if (pwincx->GetBackSurface()) {
- pwincx->SetClipOnDrawSurface(pwincx->GetBackSurface(), FE_GetMDRegion(hClipRgn));
- }
- }
- else
- CDrawable::SetClip(hClipRgn);
- #else
- CDrawable::SetClip(hClipRgn);
- #endif
- m_hClipRgn = hClipRgn;
- }
- HDC COffscreenDrawable::GetDrawableDC()
- {
- if (m_hDC)
- return m_hDC;
- else { // we must be using DirectDraw's offscreen surface.
- CWinCX *pwincx = (CWinCX*)m_parentContext;
-
- return pwincx->GetDispDC();
- }
- }
- void COffscreenDrawable::ReleaseDrawableDC(HDC hdc)
- {
- }
-
- // Get rid of any offscreen constructs if they exist
- void
- COffscreenDrawable::delete_offscreen()
- {
- if (m_hDC) {
- ::SelectObject(m_hDC, m_hSaveBitmap);
- ::SelectPalette(m_hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
- m_hSelectedPalette = 0;
- DeleteDC(m_hDC);
- }
-
- if (m_hBitmap)
- ::DeleteObject(m_hBitmap);
-
- m_hDC = NULL;
- m_hSaveBitmap = NULL;
- m_hSavePalette = NULL;
- m_hBitmap = NULL;
- m_lWidth = m_lHeight = 0;
- }
-
- COffscreenDrawable::~COffscreenDrawable()
- {
- // It's possible that the window that "owns" this offscreen
- // drawable is about to be deleted, along with its palette. We
- // have to deselect the palette from this drawable's DC so that
- // it can be safely deleted.
- if (m_hSelectedPalette && (m_hParentPal == m_hSelectedPalette)) {
- ::SelectPalette(m_hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
- m_hSelectedPalette = 0;
- }
- }
-
- void
- COffscreenDrawable::InitDrawable(CL_Drawable *pCLDrawable)
- {
- m_uRefCnt++;
- }
-
- void
- COffscreenDrawable::RelinquishDrawable(CL_Drawable *pCLDrawable)
- {
- ASSERT(m_uRefCnt > 0);
-
- if (m_uRefCnt)
- m_uRefCnt--;
-
- // There are no clients left. Let's get rid of the offscreen
- // bitmap.
- if (m_uRefCnt == 0)
- delete_offscreen();
- }
-
- // Called before using the drawable.
- PRBool
- COffscreenDrawable::LockDrawable(CL_Drawable *pCLDrawable,
- CL_DrawableState newState)
- {
-
- if (newState == CL_UNLOCK_DRAWABLE)
- return PR_TRUE;
-
- CWinCX* pWinCX = (CWinCX*)m_parentContext;
- #ifdef DDRAW
- if (!pWinCX->GetBackSurface() && !m_hBitmap)
- return PR_FALSE;
- #else
- if (!m_hBitmap)
- return PR_FALSE;
- #endif
- /*
- * Check to see if this CL_Drawable was the last one to use
- * this drawable. If not, someone else might have modified
- * the bits since the last time this CL_Drawable wrote to
- * to them.
- */
- if ((newState & CL_LOCK_DRAWABLE_FOR_READ) &&
- (m_pOwner != pCLDrawable))
- return PR_FALSE;
-
- m_pOwner = pCLDrawable;
-
- //mwh - If we are using directDraw, don't do the palette stuff..
- // If the last user of this drawable relinquished it, then
- // we need to select the new user's palette into the DC.
- #ifdef DDRAW
- if (!(pWinCX->GetBackSurface()) && !m_hSelectedPalette && m_hParentPal) {
- #else
- if (!m_hSelectedPalette && m_hParentPal) {
- #endif
- ::SelectPalette(m_hDC, m_hParentPal, FALSE);
- m_hSelectedPalette = m_hParentPal;
- }
-
- return PR_TRUE;
- }
-
- // Set the required dimensions of the drawable.
- void
- COffscreenDrawable::SetDimensions(int32 lWidth, int32 lHeight)
- {
-
- if ((lWidth > m_lWidth) || (lHeight > m_lHeight)) {
-
- /*
- * If there is only one client of the backing store,
- * we can resize it to the dimensions specified.
- * Otherwise, we can make it larger, but not smaller
- */
- if (m_uRefCnt > 1) {
- if (lWidth < m_lWidth)
- lWidth = m_lWidth;
- if (lHeight < m_lHeight)
- lHeight = m_lHeight;
- }
-
- /* If we already have a bitmap, get rid of it */
- if (m_hBitmap && m_hDC) {
- ::SelectObject(m_hDC, m_hSaveBitmap);
- ::DeleteObject(m_hBitmap);
- m_hBitmap = NULL;
- }
- CWinCX* pWinCX = (CWinCX*)m_parentContext;
-
- //mwh - If we are using directDraw, don't create a compatible DC here.
- #ifdef DDRAW
- if (!(pWinCX->GetBackSurface())) {
- #endif
- if (!m_hDC) {
- m_hDC = ::CreateCompatibleDC(m_hParentDC);
- if (!m_hDC)
- return;
-
- SetPalette(m_hParentPal);
- ::SetBkMode(m_hDC, TRANSPARENT);
- }
-
- m_hBitmap = ::CreateCompatibleBitmap(m_hParentDC,
- CASTINT(lWidth), CASTINT(lHeight));
- if (!m_hBitmap) {
- /*
- * If the bitmap allocation failed, we just delete all offscreen
- * resources and fail locking and hence, go fall back to
- * onscreen drawing.
- */
- delete_offscreen();
- }
- m_hSaveBitmap = (HBITMAP)::SelectObject(m_hDC, m_hBitmap);
- #ifdef DDRAW
- }
- #endif
- m_lWidth = lWidth;
- m_lHeight = lHeight;
- }
- }
-
- void
- COffscreenDrawable::SetPalette(HPALETTE hPal)
- {
- CWinCX* pWinCX = (CWinCX*)m_parentContext;
- #ifdef DDRAW
- if (!(pWinCX->GetBackSurface())) {
- #endif
- HPALETTE hOldPalette = NULL;
-
- if(hPal && m_hDC) {
- hOldPalette = ::SelectPalette(m_hDC, hPal, FALSE);
- // don't realize palette with memory DC.
- m_hSelectedPalette = hPal;
- }
-
- if (!m_hSavePalette)
- m_hSavePalette = hOldPalette;
- m_hParentPal = hPal;
- #ifdef DDRAW
- }
- #endif
- }
-
- PRBool
- fe_lock_drawable(CL_Drawable *drawable, CL_DrawableState state)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- return pDrawable->LockDrawable(drawable, state);
- }
-
- void
- fe_init_drawable(CL_Drawable *drawable)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->InitDrawable(drawable);
- }
-
- void
- fe_relinquish_drawable(CL_Drawable *drawable)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->RelinquishDrawable(drawable);
- }
-
- void
- fe_set_drawable_origin(CL_Drawable *drawable, int32 lOrgX, int32 lOrgY)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->SetOrigin(lOrgX, lOrgY);
- }
-
- void
- fe_get_drawable_origin(CL_Drawable *drawable, int32 *plOrgX, int32 *plOrgY)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->GetOrigin(plOrgX, plOrgY);
- }
-
- void
- fe_set_drawable_clip(CL_Drawable *drawable, FE_Region hClipRgn)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->SetClip(hClipRgn);
- }
-
- void
- fe_restore_drawable_clip(CL_Drawable *drawable)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->SetClip(NULL);
- }
-
- void
- fe_copy_pixel(CL_Drawable *pSrc, CL_Drawable *pDst, FE_Region hCopyRgn)
- {
- CDrawable *pSrcDrawable = (CDrawable *)CL_GetDrawableClientData(pSrc);
- CDrawable *pDstDrawable = (CDrawable *)CL_GetDrawableClientData(pDst);
-
- pDstDrawable->CopyPixels(pSrcDrawable, hCopyRgn);
- }
-
- void
- fe_drawable_set_dimensions(CL_Drawable *drawable, uint32 lWidth, uint32 lHeight)
- {
- CDrawable *pDrawable = (CDrawable *)CL_GetDrawableClientData(drawable);
-
- pDrawable->SetDimensions(lWidth, lHeight);
- }
-
- CL_DrawableVTable wfe_drawable_vtable = {
- fe_lock_drawable,
- fe_init_drawable,
- fe_relinquish_drawable,
- NULL,
- fe_set_drawable_origin,
- fe_get_drawable_origin,
- fe_set_drawable_clip,
- fe_restore_drawable_clip,
- fe_copy_pixel,
- fe_drawable_set_dimensions
- };
-
- #endif // LAYERS
-