gecko-dev/cmd/macfe/gui/CDeviceLoop.cp

170 строки
5.4 KiB
C++

/* -*- 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.
*/
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include "CDeviceLoop.h"
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
/*====================================================================================*/
#pragma mark CONSTANTS
/*====================================================================================*/
/*====================================================================================*/
#pragma mark INTERNAL CLASS DECLARATIONS
/*====================================================================================*/
/*====================================================================================*/
#pragma mark INTERNAL FUNCTION PROTOTYPES
/*====================================================================================*/
/*====================================================================================*/
#pragma mark CLASS IMPLEMENTATIONS
/*====================================================================================*/
#pragma mark -
/*======================================================================================
Constructor.
======================================================================================*/
CDeviceLoop::CDeviceLoop(const Rect &inLocalRect, Int16 &outFirstDepth) {
mSaveClip = nil;
mGlobalRect = inLocalRect; // Convert to Global coords
::LocalToGlobal(&topLeft(mGlobalRect));
::LocalToGlobal(&botRight(mGlobalRect));
mCurrentDevice = nil;
outFirstDepth = 0;
NextDepth(outFirstDepth);
}
/*======================================================================================
Destructor.
======================================================================================*/
CDeviceLoop::~CDeviceLoop(void) {
if ( mSaveClip != nil ) { // Restore clipping region
::SetClip(mSaveClip);
::DisposeRgn(mSaveClip);
mSaveClip = nil;
}
}
/*======================================================================================
Get the next drawing depth, return false if none.
======================================================================================*/
static Boolean RectEnclosesRect(const Rect *inEnclosingRect, const Rect *inTestRect) {
return ((inEnclosingRect->top <= inTestRect->top) &&
(inEnclosingRect->left <= inTestRect->left) &&
(inEnclosingRect->right >= inTestRect->right) &&
(inEnclosingRect->bottom >= inTestRect->bottom));
}
Boolean CDeviceLoop::NextDepth(Int16 &outNextDepth) {
if ( mCurrentDevice ) {
if ( !mSaveClip ) {
// The first device we found that contained any portion of the specified
// rectangle actually contained ALL of the rectangle, so exit here.
return false;
}
mCurrentDevice = GetNextDevice(mCurrentDevice);
} else {
mCurrentDevice = GetDeviceList();
}
// Locate the first device for processing
while ( mCurrentDevice ) {
if ( ::TestDeviceAttribute(mCurrentDevice, screenDevice) &&
::TestDeviceAttribute(mCurrentDevice, screenActive) ) {
Rect deviceRect = (**mCurrentDevice).gdRect, intersection;
if ( ::SectRect(&mGlobalRect, &deviceRect, &intersection) ) {
// Some portion of the device rect encloses the specified rect
outNextDepth = (**((**mCurrentDevice).gdPMap)).pixelSize;
if ( !mSaveClip ) {
if ( RectEnclosesRect(&deviceRect, &mGlobalRect) ) {
// Specified rectangle is completely enclosed within this device
// DON'T create a clipping region and exit here
break;
} else {
mSaveClip = ::NewRgn(); // Save clipping region
if ( mSaveClip ) {
::GetClip(mSaveClip);
}
}
}
// Set clipping region to the intersection of the target
// rectangle, the screen rectangle, and the original
// clipping region
::GlobalToLocal(&topLeft(intersection));
::GlobalToLocal(&botRight(intersection));
ClipToIntersection(intersection);
break; // Exit device loop
}
}
mCurrentDevice = ::GetNextDevice(mCurrentDevice);
}
return (mCurrentDevice != nil);
}
/*======================================================================================
Draw the control.
======================================================================================*/
void CDeviceLoop::ClipToIntersection(const Rect &inLocalRect) {
if ( mSaveClip ) {
RgnHandle overlap = ::NewRgn();
::RectRgn(overlap, &inLocalRect);
::SectRgn(mSaveClip, overlap, overlap);
::SetClip(overlap);
::DisposeRgn(overlap);
}
}