/* -*- 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.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // // This is a replacement class for PowerPlant's LGWorld. It allows for the // resizing and reorienting of the offscreen world, which LGWorld won't let // you do. Because the CGWorld can be updated, the pixmap can be made // purgeable by passing in the pixPurge flag in the constructor. LGWorld // would let you do this, however, if the pixels ever got purged you'd be // completely hosed. // // This class has ben submitted to metrowerks for a potential replacement // of LGWorld. In the event that metrowerks adds the extended functionality // that CGWorld offers, we can make this module obsolete. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ #ifdef PowerPlant_PCH #include PowerPlant_PCH #endif #include "CGWorld.h" #include "UGraphicGizmos.h" // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ CGWorld // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CGWorld::CGWorld( const Rect& inBounds, Int16 inPixelDepth, GWorldFlags inFlags, CTabHandle inCTableH, GDHandle inGDeviceH) { ::GetGWorld(&mSavePort, &mSaveDevice); mMacGWorld = nil; mBounds = inBounds; mDepth = inPixelDepth; // NewGWorld interprets the bounds in global coordinates // when specifying a zero pixel depth. It uses the maximum // depth of all screen devices intersected by the bounds. Rect gwRect = inBounds; if (inPixelDepth == 0) { LocalToGlobal(&topLeft(gwRect)); LocalToGlobal(&botRight(gwRect)); } mGWorldStatus = ::NewGWorld(&mMacGWorld, inPixelDepth, &gwRect, inCTableH, inGDeviceH, inFlags); ThrowIfOSErr_(mGWorldStatus); ThrowIfNil_(mMacGWorld); // Set up coordinates and erase pixels in GWorld ::SetGWorld(mMacGWorld, nil); ::SetOrigin(mBounds.left, mBounds.top); ::LockPixels(::GetGWorldPixMap(mMacGWorld)); ::EraseRect(&mBounds); ::UnlockPixels(::GetGWorldPixMap(mMacGWorld)); ::SetGWorld(mSavePort, mSaveDevice); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ CGWorld // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // This does not initialize the GWorld. Must be overriden. CGWorld::CGWorld() { } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ ~CGWorld // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CGWorld::~CGWorld() { if (mMacGWorld != nil) ::DisposeGWorld(mMacGWorld); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ BeginDrawing // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CGWorld::BeginDrawing(void) { Boolean bReadyToDraw = false; // The mac GWolrd will be inconsistent if a previous call to UpdateGWorld() // has failed. We get one more shot a fixing that here before we draw. if (!IsConsistent()) AdjustGWorld(mBounds); if (IsConsistent()) { if (!::LockPixels(::GetGWorldPixMap(mMacGWorld))) { // This means we're consistentlty sized and oriented, but our pixMap // data has been purged. AdjustGWorld(mBounds); if (IsConsistent()) bReadyToDraw = ::LockPixels(::GetGWorldPixMap(mMacGWorld)); } else bReadyToDraw = true; } if (bReadyToDraw) { ::GetGWorld(&mSavePort, &mSaveDevice); ::SetGWorld(mMacGWorld, nil); } return bReadyToDraw; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ EndDrawing // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CGWorld::EndDrawing(void) { Assert_(IsConsistent()); // You should have noticed that // BeginDrawing() returned false ::UnlockPixels(::GetGWorldPixMap(mMacGWorld)); ::SetGWorld(mSavePort, mSaveDevice); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ CopyImage // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CGWorld::CopyImage( GrafPtr inDestPort, const Rect& inDestRect, Int16 inXferMode, RgnHandle inMaskRegion) { ::CopyBits(&((GrafPtr)mMacGWorld)->portBits, &inDestPort->portBits, &mBounds, &inDestRect, inXferMode, inMaskRegion); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ SetBounds // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CGWorld::SetBounds(const Rect &inBounds) { if (::EqualRect(&inBounds, &mBounds)) return; UpdateBounds(inBounds); // Note that even if we're not consistent, we still remember the bounds so that // the next time through BeginDrawing() we can attempt to realloc for the // size it's supposed to be. mBounds = inBounds; // We've reallocted successfully. Now lets get the origin set properly. if (IsConsistent()) UpdateOrigin(topLeft(mBounds)); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ AdjustGWorld // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CGWorld::AdjustGWorld(const Rect& inBounds) { UpdateBounds(inBounds); if (IsConsistent()) UpdateOrigin(topLeft(inBounds)); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ UpdateBounds // // Internal method which is called when the offscreen world needs to change // it's dimensions. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CGWorld::UpdateBounds(const Rect& inBounds) { Rect theNewBounds; if (mDepth == 0) { theNewBounds = inBounds; ::LocalToGlobal(&topLeft(theNewBounds)); ::LocalToGlobal(&botRight(theNewBounds)); } else theNewBounds = inBounds; GWorldFlags theFlags = ::UpdateGWorld(&mMacGWorld, mDepth, &theNewBounds, NULL, NULL, 0); if (theFlags & gwFlagErr) mGWorldStatus = ::QDError(); else mGWorldStatus = noErr; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ UpdateOrigin // // Internal method in which the origin on the offscreen world needs to be // offset to match the on-screen representation. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CGWorld::UpdateOrigin(const Point& inOrigin) { ::GetGWorld(&mSavePort, &mSaveDevice); ::SetGWorld(mMacGWorld, nil); ::SetOrigin(inOrigin.h, inOrigin.v); ::SetGWorld(mSavePort, mSaveDevice); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CSharedWorld::CSharedWorld( const Rect& inFrame, Int16 inDepth, GWorldFlags inFlags) : CGWorld(inFrame, inDepth, inFlags) { }