/*********************************************************************************
File: SmartPDPage.h
Created: June 16, 2003
Purpose: This class contains a thin wrapper for PDPage objects that
ensures the reference count is decremented when the object
is destroyed.
*
* ___________________
*
* (c) Copyright 2002-2006 Adobe Systems, Inc.
* All Rights Reserved.
*
* NOTICE: Adobe permits you to use, modify, and distribute this file
* in accordance with the terms of the Adobe license agreement
* accompanying it. If you have received this file from a source other
* than Adobe, then your use, modification, or distribution of it
* requires the prior written permission of Adobe.
************************************************************************************/
#ifndef _SMARTPDPAGE_H
#define _SMARTPDPAGE_H
#if defined (__cplusplus)
/* Include common macros */
#include "PDClassDefs.h"
/* Set ENABLE_SMARTPDPAGETESTS to 1 to enable unit tests for the class */
#define ENABLE_SMARTPDPAGETESTS 0
/**
This class ensures that PDPage objects are released even in case
of exceptions and RAISE
. There are many ways to acquire a Page that
we need to be careful about, and those APIs are listed below:
Note that PDPage objects retrieved using AVPageViewGetPage() should not be released.
This class is modeled based on a SmartPointer
class. It does not
have a release()
API, as there was a clash in the meaning of the API
in the auto_ptr
domain and the PD
API domain.
This class is designed to be a Final
class, and hence does not
have a virtual destructor. Classes that need this functionality
should encapsulate it using containment.
This is the default constructor. It is used along with AssignAndTakeOwnership() or the AcquirePage() method.
*/ CSmartPDPage(): m_pdPage(NULL) { CTOR; /* Macro for creating a RaiseAwareConstructor */ } /** Constructor.This is a constructor for the most common PDPage creation APIs. Modules using this class should never call the PDDocAcquirePage() directly.
@param pdDoc The PDDoc containing the page that is requested. This cannot beNULL
.
@param nPageNum The page number of the page that is requested. This cannot
be negative and should be in the page range of the document.
*/
CSmartPDPage(PDDoc pdDoc, ASInt32 nPageNum): m_pdPage(NULL)
{
CTOR; /* Macro for creating a RaiseAwareConstructor */
AssignPage(pdDoc, nPageNum);
}
/**
Constructor.
This constructor takes a PDPage pointer as parameter. It increases the reference count of the object before taking ownership of the PDPage pointer passed in. It is to be used in cases where the PDPage pointer is acquired by APIs that do not increase the reference count (for example, AVPageViewGetPage()).
@param pdPage The Page object. This should not beNULL
.
@example CSmartPDPage cPDPage(AVPageViewGetPage(avPageView));
*/
explicit CSmartPDPage( PDPage pdPage): m_pdPage(NULL)
{
CTOR; /* Macro for creating a RaiseAwareConstructor */
AssignPage(pdPage);
}
/**
Copy Constructor.
It increases the reference count of the contained PDPage object in case
it is not NULL
.
If the PDPage object is not empty, then it
releases the PDPage object. This method is not a virtual method,
since the class is supposed to be a Final
class.
In the case of an exception, the object will be set to the empty state.
@param pdDoc The PDDoc containing the page that is requested. This cannot beNULL
.
@param nPageNum The page number of the page that is requested. This cannot
be negative and should be in the page range of the document.
*/
void AcquirePage(PDDoc pdDoc, ASInt32 nPageNum)
{
/* Release the current PDPage object. */
Reset();
/* Acquire a new page */
AssignPage(pdDoc, nPageNum);
}
/**
The old PDPage pointer contained within is released. It then takes ownership
of the PDPage pointer passed in as parameter. The method does not increase the
reference count of the passed in PDPage object. This method is used in scenarios
where the Smart
pointer needs to be constructed before
the page object becomes available. It is also used with APIs like
PDPageAcquireFromCosPage() that have already increased the reference count for
the PDPage object but are not encapsulated by the class methods.
In the case of an exception, the object will be set to the empty state.
@param pdPage The Page object. It cannot beNULL
.
*/
void AssignAndTakeOwnership(PDPage pdPage)
{
ACROASSERT(pdPage != NULL);
/* Release the current PDPage object. */
Reset();
/* Take ownership of the new PDPage object. */
m_pdPage = pdPage;
}
/**
PDPage operator.
This is an operator to access the PDPage pointer contained within. This gives access to the raw pointer within and hence should not be released. The lifetime of the PDPage pointer returned is bound to the CSmartPDPage object that returned it.
This does not raise exceptions.
@return The PDPage contained in this object. It may beNULL
.
*/
inline operator PDPage ( void ) const
{
return m_pdPage;
}
/**
Assignment operator.
This copies the PDPage pointer contained within the CSmartPDPage object passed
in as parameter. It increases the reference count in case the PDPage pointer
contained within the passed in object is not NULL
.
In the case of an exception, the object will be set to the empty state.
@param hRhs The Page object. @return A reference tothis
.
*/
CSmartPDPage& operator=( const CSmartPDPage& hRhs )
{
if( this != &hRhs )
{
/* Release the current PDPage object. */
Reset();
/* Assign and increase the refcount for the page. */
if (hRhs.m_pdPage != NULL)
AssignPage(hRhs.m_pdPage);
}
return *this;
}
/**
This method releases ownership of the internal PDPage object. The caller
will be responsible for releasing the PDPage object. The PDPage object
contained within will be empty once this API is called, and hence should not
be used.
This does not raise exceptions.
@return the PDPage that was contained in this object. This can beNULL
.
*/
PDPage GiveOwnershipToCaller()
{
PDPage pdRetVal = m_pdPage;
m_pdPage = NULL;
return pdRetVal;
}
/**
Releases the PDPage object. In case the object
is empty, this method does not do anything. The PDPage object will
no longer be valid once this method is called, and hence should not be used.
In the case of an exception, the object will be set to the empty state.
*/ void Reset() { if (m_pdPage != NULL) { // The method 'PDPageRelease' may raise and hence we need to reset the value before this PDPage tmpPage = m_pdPage; m_pdPage = NULL; ASTRY { PDPageRelease(tmpPage); } END_ASTRY } } /* Run the following tests when changing the class */ #if (ENABLE_SMARTPDPAGETESTS) static void UnitTestSmartPDPage(PDPage pdPageOwnedByCaller, PDDoc pdDoc, ASInt32 nPageNum) { ////////////////////////////////////// // Test Code to test CSmartPDPage // ASRaise test DURING { CSmartPDPage pdPage(pdPageOwnedByCaller); ASRaise(0); } HANDLER END_HANDLER // Method tests { // Constructor CSmartPDPage pdPage(pdDoc, nPageNum); // PDPage operator CSmartPDPage pdCopy = pdPage; // Copy constructor CSmartPDPage pdCopy2; CSmartPDPage pdCopy3(pdCopy2); CSmartPDPage pdCopy4(pdCopy); // Release PDPageRelease(pdCopy.GiveOwnershipToCaller()); //Assignment operator pdPage = pdCopy4; pdPage = pdCopy; //Assign and take ownership pdPage.AssignAndTakeOwnership(pdCopy4.GiveOwnershipToCaller()); // Acquire page pdPage.AcquirePage(pdDoc, nPageNum); // Reset pdPage.Reset(); // Destructor { CSmartPDPage pdPageDesTest, nullPDPageTest; pdPageDesTest.AcquirePage(pdDoc, nPageNum); } } } #endif /* ENABLE_SMARTPDPAGETESTS */ private: #if (NEEDS_RAISEAWARE) /* The volatile keyword is needed in a RAISE scenario */ PDPage volatile m_pdPage; #else PDPage m_pdPage; #endif /** PDPage assignment operator.There is no clear way to handle this operator. It could be used as
AssignAndTakeOwnership()
(the reference count is unchanged) or AcquirePage(),
where the reference count is increased by 1
. Hence we have made this
private so that the unambiguous APIs are explicitly used.
In the case of an exception, the object will be set to the empty state.
@param pdPage The Page object. This should not beNULL
.
*/
void AssignPage(PDPage pdPage)
{
ACROASSERT((m_pdPage == NULL) && (pdPage != NULL));
/* Assign and increase the refcount for the page. */
ASTRY
{
PDPageAcquirePage(pdPage);
m_pdPage = pdPage;
}
END_ASTRY;
}
/**
Wrapper for PDDocAcquirePage(). This API assumes that there is no
PDPage object.
In the case of an exception, the object will be set to the empty state.
@param pdDoc The PDDoc containing the page that is requested. This cannot beNULL
.
@param nPageNum The page number of the page that is requested. This cannot
be negative and should be in the page range of the document.
*/
void AssignPage(PDDoc pdDoc, ASInt32 nPageNum)
{
ACROASSERT((m_pdPage == NULL) && (pdDoc != NULL) && (nPageNum >= 0));
/* Acquire the page. */
ASTRY
{
m_pdPage = PDDocAcquirePage(pdDoc, nPageNum);
}
END_ASTRY;
}
};
#if CPP_EXCEPTIONS
#undef ERRFILE
#endif
#endif /* __cplusplus */
#endif /* _SMARTPDPAGE_H */