EPSClipContext Class Reference

Used to maintain clipping regions (masks) while importing Illustrator EPS. A stack of regions is maintained, similar to attribute rendering, with the usual save/restore semantics. Adding a new clipping region results in the new clipping region being merged with the current clipping region. In this way complex paths can be used to build up complex masks (this is the brain-damaged way AI EPS does it anyway). More...

#include <epsfiltr.h>

Inheritance diagram for EPSClipContext:

List CCObject SimpleCCObject List of all members.

Public Member Functions

 EPSClipContext ()
 Initialise the context to a sensible state, i.e. a zero context level.
void SaveContext ()
 Save the current clipping state for future use - no matter how many clip regions are added to the current context, the exact state of the current clipping context can be restore with a (balanced) call to EPSClipContext::RestoreContext().
BOOL RestoreContext ()
 Restores the clipping context to the state it was in the last time SaveContext() was called on this clip context.
BOOL AddNewClippingPath (Path *pNewClipPath)
 Takes a copy of the path passed in and merges it with the current clipping context.
BOOL StartComplexClipRegion ()
 Indicates that we are about to start constructing a complex clipping region. All future calls to AddNewClippingPath() will be joined into the current clipping region until EndComplexRegion is called. Note that you cannot interleave these calls with Save/Restore context calls; complex regions cannot be unbalanced across context levels.
BOOL EndComplexClipRegion ()
 See StartComplexClipRegion().
BOOL ClipPathToRegion (Path *pPathToClip)
 Given a path, clip it to the current clipping region specified by this object.
PathGetClipRegion ()
 Get the path which defines the current clipping region ofheld by this object.
void SetClippingFlags (UINT32 NewFlags)

Protected Attributes

INT32 ContextLevel
INT32 ComplexRegionLevel
PathpCachedClipPath
BOOL CacheIsValid
UINT32 ClippingFlags

Detailed Description

Used to maintain clipping regions (masks) while importing Illustrator EPS. A stack of regions is maintained, similar to attribute rendering, with the usual save/restore semantics. Adding a new clipping region results in the new clipping region being merged with the current clipping region. In this way complex paths can be used to build up complex masks (this is the brain-damaged way AI EPS does it anyway).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
See also:
EPSFilter

Definition at line 356 of file epsfiltr.h.


Constructor & Destructor Documentation

EPSClipContext::EPSClipContext  ) 
 

Initialise the context to a sensible state, i.e. a zero context level.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95

Definition at line 436 of file epsfiltr.cpp.

00437 {
00438     ContextLevel = 0;
00439     ComplexRegionLevel = 0;
00440 
00441     // Initially there is no clip region.
00442     pCachedClipPath = NULL;
00443     CacheIsValid = TRUE;
00444 
00445     // set default clipping flags
00446     ClippingFlags = 2 | CLIPPING_CLIP_WINDING;
00447 }


Member Function Documentation

BOOL EPSClipContext::AddNewClippingPath Path pNewClipPath  ) 
 

Takes a copy of the path passed in and merges it with the current clipping context.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
Parameters:
The path to augment the current clipping region with. [INPUTS]
Returns:
TRUE if clipping region updated ok; FALSE if not, i.e. out of memory => ERROR1

Errors: Out of memory => ERROR1

Definition at line 591 of file epsfiltr.cpp.

00592 {
00593     // Invalidate cache
00594     CacheIsValid = FALSE;
00595 
00596     // Flag to indicate if we just do a straightforward copy
00597     BOOL SimpleCopy = FALSE;
00598 
00599     EPSClipContextItem *pItem = NULL;
00600 
00601     if (ComplexRegionLevel > 0)
00602     {
00603         // We are building a complex region, so join the new path with the existing one.
00604 
00605         // First, make sure we have a clip path already?
00606         pItem = (EPSClipContextItem *) GetTail();
00607         if (pItem->pClipPath == NULL)
00608         {
00609             // No clip path - just copy the new path and use that.
00610             SimpleCopy = TRUE;
00611         }
00612         else
00613         {
00614             // Already have a clip path - join with new one to form a complex path.
00615             if (!pItem->pClipPath->MergeTwoPaths(*pNewClipPath))
00616                 // Error occured (i.e. out of memory)
00617                 return FALSE;
00618         }
00619     }
00620     else
00621     {
00622         // Just a simple clipping region
00623         pItem = new EPSClipContextItem(ContextLevel, NULL);
00624 
00625         if (pItem == NULL)
00626             // Out of memory
00627             return FALSE;
00628 
00629         // Add to end of list
00630         AddTail(pItem);
00631 
00632         // Just copy the path passed in
00633         SimpleCopy = TRUE;
00634     }
00635 
00636     // Should we just copy the path into the list item?
00637     if (SimpleCopy)
00638     {
00639         // Sanity check
00640         ERROR2IF(pItem == NULL, FALSE, "No clipping item found!");
00641 
00642         // (yes, this code is pretty tedious!)
00643         pItem->pClipPath = new Path;
00644 
00645         if (pItem->pClipPath == NULL)
00646             // Out of memory
00647             return FALSE;
00648 
00649         // Graeme (26/7/00) - Added a test for a NULL pointer to prevent access violations.
00650         if ( pNewClipPath != NULL &&
00651              !pItem->pClipPath->Initialise ( pNewClipPath->GetNumCoords () + 3, 12 ) )
00652         {
00653             // Failed to initialise - out of memory
00654             return FALSE;
00655         }
00656 
00657         if (!pItem->pClipPath->CopyPathDataFrom(pNewClipPath))
00658             // Failed to copy - out of memory - but this shouldn't happen as
00659             // we made sure we had enough space with the initialise call!
00660             ERROR2(FALSE, "Unexpected out-of-space error when copying clipping path");
00661     }
00662 
00663     // If we've got here, it must have worked...
00664     return TRUE;
00665 }

BOOL EPSClipContext::ClipPathToRegion Path pPathToClip  ) 
 

Given a path, clip it to the current clipping region specified by this object.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
Parameters:
pPathToClip - the path object that we want to clip [INPUTS]
pPathToClip - the clipped version of the path [OUTPUTS]
Returns:
TRUE if clipped ok; FALSE if not.
See also:
EPSClipContext::GetClipRegion

Definition at line 684 of file epsfiltr.cpp.

00685 {
00686     // Cope with NULL clip region first
00687     if (GetClipRegion() == NULL)
00688         // Path is already 'clipped'
00689         return TRUE;
00690 
00691     // Ensure GetClipRegion validated the cache
00692     ERROR2IF(!CacheIsValid, FALSE, 
00693              "Could not get valid clipping path in EPSClipContext::ClipPathToRegion()");
00694 
00695     // We now have a valid region, so use it to clip the given path
00696     // NB. we do an intersection using the cliping path's winding, with a tolerance of 0,
00697     //     and flatness of 128 millipoints (arbitrary).
00698     if (pCachedClipPath->ClipPathToPath(*pPathToClip, pPathToClip, ClippingFlags, 
00699                                         128, 256, 256) == -1)
00700     {
00701         // An error occured...
00702         return FALSE;
00703     }
00704 
00705     // Initialise flags so the bezier tool is happy 
00706     // [see comment for Path::ClipPathToPath()].
00707     pPathToClip->InitialiseFlags();
00708 
00709     // If we get this far, it worked!
00710     return TRUE;
00711 }

BOOL EPSClipContext::EndComplexClipRegion  ) 
 

See StartComplexClipRegion().

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
Returns:
TRUE if ok; FALSE if no corresponding call to StartComplexClipRegion() has been encountered => ERROR2

Errors: If unbalanced call is made => ERROR2

See also:
EPSClipContext::StartComplexClipRegion

Definition at line 563 of file epsfiltr.cpp.

00564 {
00565     ERROR2IF(ComplexRegionLevel == 0, FALSE, 
00566              "Unbalanced call to EPSClipContext::EndComplexClipRegion()");
00567 
00568     // Adjust complex region level.
00569     ComplexRegionLevel--;
00570 
00571     // All ok
00572     return TRUE;
00573 }

Path * EPSClipContext::GetClipRegion  ) 
 

Get the path which defines the current clipping region ofheld by this object.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
Returns:
Pointer to the clipping path, or NULL if no clipping region is specified by this object.
See also:
EPSClipContext::ClipPathToRegion

Definition at line 727 of file epsfiltr.cpp.

00728 {
00729     if (!CacheIsValid)
00730     {
00731         // Cache is invalid - if there is no path in the cache, get a new one, otherwise
00732         // empty the one in the cache and use that.
00733         if (pCachedClipPath == NULL)
00734         {
00735             pCachedClipPath = new Path;
00736 
00737             if (pCachedClipPath == NULL)
00738                 // Out of memory
00739                 return NULL;
00740 
00741             if (!pCachedClipPath->Initialise(12, 12))
00742                 // Failed to initialise - out of memory
00743                 return NULL;
00744         }
00745         else
00746         {
00747             // Just clear this path out so we can use it to build a clipping region.
00748             pCachedClipPath->ClearPath();
00749         }
00750 
00751         // Calculate the current clipping path - we do this by going along the region
00752         // list and combining the clip regions.
00753         EPSClipContextItem *pItem = (EPSClipContextItem *) GetHead();
00754 
00755         while (pItem != NULL)
00756         {
00757             if (pItem->pClipPath != NULL)
00758             {
00759                 // Do we already have a clipping region?
00760                 if (pCachedClipPath->GetNumCoords() > 0)
00761                 {
00762                     // Combine this clipping region with the region being constructed...
00763                     if (pItem->pClipPath->ClipPathToPath(*pCachedClipPath, pCachedClipPath, 
00764                                                          2 | CLIPPING_CLIP_WINDING, 
00765                                                          128, 256, 256) == -1)
00766                     {
00767                         // An error occured...
00768                         return FALSE;
00769                     }
00770                 }
00771                 else
00772                 {
00773                     // No clipping region yet - just copy the data from this path
00774                     if (!pCachedClipPath->MakeSpaceInPath(pItem->pClipPath->GetNumCoords() + 3))
00775                         // Failed to initialise - out of memory
00776                         return FALSE;
00777 
00778                     if (!pCachedClipPath->CopyPathDataFrom(pItem->pClipPath))
00779                         // Failed to copy - out of memory - but this shouldn't happen as
00780                         // we made sure we had enough space with the initialise call!
00781                         ERROR2(FALSE, "Unexpected out-of-space error when copying clipping path");
00782                 }
00783             }
00784 
00785             // Get the next item
00786             pItem = (EPSClipContextItem *) GetNext(pItem);
00787         }
00788 
00789         // Did we get any clipping at all?
00790         if (pCachedClipPath->GetNumCoords() == 0)
00791         {
00792             // No clip region - delete and use NULL to indicate this.
00793             delete pCachedClipPath;
00794             pCachedClipPath = NULL;
00795         }
00796 
00797         // Validate cache
00798         CacheIsValid = TRUE;
00799     }
00800 
00801     // Cache must be valid, so return the contents of the cache.
00802     return pCachedClipPath;
00803 }

BOOL EPSClipContext::RestoreContext  ) 
 

Restores the clipping context to the state it was in the last time SaveContext() was called on this clip context.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
Returns:
Errors: No call to SaveContext() has been made => ERROR2
See also:
EPSClipContext::SaveContext

Definition at line 481 of file epsfiltr.cpp.

00482 {
00483     // Invalidate cache
00484     CacheIsValid = FALSE;
00485 
00486     // Sanity check
00487     ERROR2IF(ContextLevel == 0, FALSE, "Unbalanced call to EPSClipContext::RestoreContext()");
00488 
00489     // Decrement context level
00490     ContextLevel--;
00491 
00492     // Delete all items added since save context was last called...
00493     EPSClipContextItem *pItem = (EPSClipContextItem *) GetTail();
00494 
00495     while ((pItem != NULL) && (pItem->ContextLevel > ContextLevel))
00496     {
00497         delete RemoveTail();
00498         
00499         // Get the next item
00500         pItem = (EPSClipContextItem *) GetTail();
00501     }
00502 
00503     // If we get here then it's ok
00504     return TRUE;
00505 }

void EPSClipContext::SaveContext  ) 
 

Save the current clipping state for future use - no matter how many clip regions are added to the current context, the exact state of the current clipping context can be restore with a (balanced) call to EPSClipContext::RestoreContext().

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
See also:
EPSClipContext::RestoreContext

Definition at line 463 of file epsfiltr.cpp.

00464 {
00465     ContextLevel++;
00466 }

void EPSClipContext::SetClippingFlags UINT32  NewFlags  )  [inline]
 

Definition at line 369 of file epsfiltr.h.

00369 {ClippingFlags = NewFlags;};

BOOL EPSClipContext::StartComplexClipRegion  ) 
 

Indicates that we are about to start constructing a complex clipping region. All future calls to AddNewClippingPath() will be joined into the current clipping region until EndComplexRegion is called. Note that you cannot interleave these calls with Save/Restore context calls; complex regions cannot be unbalanced across context levels.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/22/95
Returns:
TRUE if ok; FALSE if out of memory.

Errors: Out of memory => ERROR1

See also:
EPSClipContext::EndComplexClipRegion()

Definition at line 526 of file epsfiltr.cpp.

00527 {
00528     // Update complex region count
00529     ComplexRegionLevel++;
00530 
00531     // We need to create a record to hold this complex region
00532     // (it has a NULL clipping region initially)
00533     EPSClipContextItem *pItem = new EPSClipContextItem(ContextLevel, NULL);
00534     if (pItem == NULL)
00535         // Out of memory
00536         return FALSE;
00537 
00538     // It's a complex region so save the level
00539     pItem->ComplexRegionLevel = ComplexRegionLevel;
00540 
00541     // Add to end of list
00542     AddTail(pItem);
00543 
00544     // All ok
00545     return TRUE;
00546 }


Member Data Documentation

BOOL EPSClipContext::CacheIsValid [protected]
 

Definition at line 375 of file epsfiltr.h.

UINT32 EPSClipContext::ClippingFlags [protected]
 

Definition at line 376 of file epsfiltr.h.

INT32 EPSClipContext::ComplexRegionLevel [protected]
 

Definition at line 373 of file epsfiltr.h.

INT32 EPSClipContext::ContextLevel [protected]
 

Definition at line 369 of file epsfiltr.h.

Path* EPSClipContext::pCachedClipPath [protected]
 

Definition at line 374 of file epsfiltr.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:53:59 2007 for Camelot by  doxygen 1.4.4