ndbldpth.cpp

Go to the documentation of this file.
00001 // $Id: ndbldpth.cpp 1282 2006-06-09 09:46:49Z alex $
00002 // NodeBlendPath implementation. This file controls the tree node 'mouldpath'
00003 // which is the shape of the mould for perspective and envelope shapes.
00004 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00005 ================================XARAHEADERSTART===========================
00006  
00007                Xara LX, a vector drawing and manipulation program.
00008                     Copyright (C) 1993-2006 Xara Group Ltd.
00009        Copyright on certain contributions may be held in joint with their
00010               respective authors. See AUTHORS file for details.
00011 
00012 LICENSE TO USE AND MODIFY SOFTWARE
00013 ----------------------------------
00014 
00015 This file is part of Xara LX.
00016 
00017 Xara LX is free software; you can redistribute it and/or modify it
00018 under the terms of the GNU General Public License version 2 as published
00019 by the Free Software Foundation.
00020 
00021 Xara LX and its component source files are distributed in the hope
00022 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00023 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00024 See the GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License along
00027 with Xara LX (see the file GPL in the root directory of the
00028 distribution); if not, write to the Free Software Foundation, Inc., 51
00029 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00030 
00031 
00032 ADDITIONAL RIGHTS
00033 -----------------
00034 
00035 Conditional upon your continuing compliance with the GNU General Public
00036 License described above, Xara Group Ltd grants to you certain additional
00037 rights. 
00038 
00039 The additional rights are to use, modify, and distribute the software
00040 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00041 library and any other such library that any version of Xara LX relased
00042 by Xara Group Ltd requires in order to compile and execute, including
00043 the static linking of that library to XaraLX. In the case of the
00044 "CDraw" library, you may satisfy obligation under the GNU General Public
00045 License to provide source code by providing a binary copy of the library
00046 concerned and a copy of the license accompanying it.
00047 
00048 Nothing in this section restricts any of the rights you have under
00049 the GNU General Public License.
00050 
00051 
00052 SCOPE OF LICENSE
00053 ----------------
00054 
00055 This license applies to this program (XaraLX) and its constituent source
00056 files only, and does not necessarily apply to other Xara products which may
00057 in part share the same code base, and are subject to their own licensing
00058 terms.
00059 
00060 This license does not apply to files in the wxXtra directory, which
00061 are built into a separate library, and are subject to the wxWindows
00062 license contained within that directory in the file "WXXTRA-LICENSE".
00063 
00064 This license does not apply to the binary libraries (if any) within
00065 the "libs" directory, which are subject to a separate license contained
00066 within that directory in the file "LIBS-LICENSE".
00067 
00068 
00069 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00070 ----------------------------------------------
00071 
00072 Subject to the terms of the GNU Public License (see above), you are
00073 free to do whatever you like with your modifications. However, you may
00074 (at your option) wish contribute them to Xara's source tree. You can
00075 find details of how to do this at:
00076   http://www.xaraxtreme.org/developers/
00077 
00078 Prior to contributing your modifications, you will need to complete our
00079 contributor agreement. This can be found at:
00080   http://www.xaraxtreme.org/developers/contribute/
00081 
00082 Please note that Xara will not accept modifications which modify any of
00083 the text between the start and end of this header (marked
00084 XARAHEADERSTART and XARAHEADEREND).
00085 
00086 
00087 MARKS
00088 -----
00089 
00090 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00091 designs are registered or unregistered trademarks, design-marks, and/or
00092 service marks of Xara Group Ltd. All rights in these marks are reserved.
00093 
00094 
00095       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00096                         http://www.xara.com/
00097 
00098 =================================XARAHEADEREND============================
00099  */
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 #include "blobs.h"
00106 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "nodeblnd.h"
00109 #include "objchge.h"
00110 //#include "undoop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "ndbldpth.h"
00112 //#include "tool.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "ngcore.h"       // NameGallery, for stretching functionality
00114 
00115 //#include "aw_eps.h"
00116 //#include "nativeps.h"     // The old style EPS native filter, used in v1.1
00117 //#include "app.h"
00118 
00119 #include "cxftags.h"
00120 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00121 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 //#include "tim.h"
00123 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 
00125 #include "ophist.h"
00126 
00127 
00128 DECLARE_SOURCE("$Revision: 1282 $");
00129 
00130 CC_IMPLEMENT_DYNCREATE(NodeBlendPath,NodePath);
00131 CC_IMPLEMENT_DYNCREATE(InitNodeBlendPathAction,Action);
00132 
00133 // Declare smart memory handling in Debug builds
00134 #define new CAM_DEBUG_NEW
00135 
00136 // Uncomment this #define out if you want the code to cache the points it reads from the path
00137 // in the function GetPointAtDistance()
00138 // The reason it's been taken out is because the CMap<> template class seems to clash with the
00139 // CAM_DEBUG_NEW mechanism, resulting in potential memory corruption.
00140 #define NBP_CACHEPOINTATDISTANCE
00141 
00142 /*********************************************************************************************
00143 
00144 >    NodeBlendPath::NodeBlendPath() 
00145 
00146      Author:    Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00147      Created:   29/4/99
00148      Purpose:   This constructor creates a NodeBlendPath linked to no other, with all status
00149                 flags false and an uninitialised bounding rectangle.           
00150 
00151 **********************************************************************************************/
00152  
00153 NodeBlendPath::NodeBlendPath(): NodePath()
00154 {
00155     m_pCachedPointsAtDistance = NULL;
00156     // Reuse the "Initialise cache" call
00157     DestroyCachedInformation();
00158     m_Index = 0;
00159 }
00160 
00161 /***********************************************************************************************
00162 
00163 >   void NodeBlendPath::NodeBlendPath
00164     (
00165         Node* ContextNode,  
00166         AttachNodeDirection Direction,  
00167         BOOL Locked = FALSE, 
00168         BOOL Mangled = FALSE,  
00169         BOOL Marked = FALSE, 
00170         BOOL Selected = FALSE, 
00171     )
00172 
00173     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00174     Created:    29/4/99
00175     Inputs:     ContextNode: Pointer to a node which this node is to be attached to.     
00176     
00177                 Direction: 
00178             
00179                     Specifies the direction in which this node is to be attached to the 
00180                     ContextNode. The values this variable can take are as follows: 
00181                                       
00182                     PREV      : Attach node as a previous sibling of the context node
00183                     NEXT      : Attach node as a next sibling of the context node
00184                     FIRSTCHILD: Attach node as the first child of the context node
00185                     LASTCHILD : Attach node as a last child of the context node                               
00186                           
00187                 The remaining inputs specify the status of the node: 
00188             
00189                 Locked:     Is node locked ?
00190                 Mangled:    Is node mangled ?
00191                 Marked:     Is node marked ?
00192                 Selected:   Is node selected ?
00193             
00194     Outputs: -
00195     Returns: - 
00196     Purpose:    This method initialises the node and links it to ContextNode in the
00197                 direction specified by Direction. All necessary tree links are
00198                 updated.     
00199              
00200     Errors:     An assertion error will occur if ContextNode is NULL
00201 
00202 
00203 ***********************************************************************************************/
00204 
00205 NodeBlendPath::NodeBlendPath(Node* ContextNode,  
00206                              AttachNodeDirection Direction,  
00207                              BOOL Locked, 
00208                              BOOL Mangled,  
00209                              BOOL Marked, 
00210                              BOOL Selected   
00211                ):NodePath(ContextNode, Direction, Locked, Mangled, Marked, Selected) 
00212 { 
00213     m_pCachedPointsAtDistance = NULL;
00214     // Reuse the "Destroy cache" call
00215     DestroyCachedInformation();
00216     m_Index = 0;
00217 } 
00218 
00219 /*********************************************************************************************
00220 
00221 >    NodeBlendPath::~NodeBlendPath() 
00222 
00223      Author:    Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00224      Created:   29/4/99
00225      Purpose:   Destructor for Node MouldPath. This does nothing at present.
00226 
00227 **********************************************************************************************/
00228  
00229 NodeBlendPath::~NodeBlendPath()
00230 {
00231     // Reuse the "Destroy cache" call
00232     DestroyCachedInformation();
00233 }
00234 
00235 
00236 /***********************************************************************************************
00237 
00238 >   virtual Node* NodeBlendPath::SimpleCopy()
00239 
00240     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00241     Created:    29/4/99
00242     Returns:    Pointer to a Node
00243     Purpose:    Makes a copy of all the data in the node
00244 
00245 ***********************************************************************************************/
00246 
00247 Node* NodeBlendPath::SimpleCopy()
00248 {
00249     NodeBlendPath* NodeCopy = new NodeBlendPath();
00250     if (NodeCopy)
00251         CopyNodeContents(NodeCopy);
00252     
00253     return NodeCopy;
00254 }            
00255 
00256 
00257 /***********************************************************************************************
00258 
00259 >   void NodeBlendPath::CopyNodeContents(NodeBlendPath* NodeCopy)
00260 
00261     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00262     Created:    29/4/99
00263     Inputs:     NodeCopy - The node to copy
00264     Purpose:    Copies the data in the node by first calling the base class to get it to
00265                 copy its stuff, and then copying its own stuff
00266     Scope:      protected
00267     SeeAlso:    NodeRenderableInk::CopyNodeContents
00268 
00269 ***********************************************************************************************/
00270 
00271 void NodeBlendPath::CopyNodeContents( NodeBlendPath* NodeCopy)
00272 {
00273     NodePath::CopyNodeContents( NodeCopy );
00274     //Copy contents specific to derived class here
00275 }
00276 
00277 /***********************************************************************************************
00278 
00279 >   BOOL NodeBlendPath::CopyNodePath(NodePath* pNodePathToCopy)
00280 
00281     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00282     Created:    29/4/99
00283     Inputs:     pNodePathToCopy
00284     Purpose:    Copies the data in the node by first calling the base class to get it to
00285                 copy its stuff, and then copying its own stuff
00286     Scope:      protected
00287     SeeAlso:    NodeRenderableInk::CopyNodeContents
00288 
00289 ***********************************************************************************************/
00290 
00291 BOOL NodeBlendPath::CopyNodePath(NodePath* pNodePathToCopy)
00292 {
00293     ERROR2IF(pNodePathToCopy == NULL,FALSE,"NULL NodePath ptr");
00294 
00295     BOOL    ok = SetUpPath();
00296     if (ok) ok = InkPath.MergeTwoPaths(pNodePathToCopy->InkPath);
00297 
00298     return ok;
00299 }
00300 
00301 
00302 
00303 /***********************************************************************************************
00304 >   void NodeBlendPath::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00305 
00306     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00307     Created:    18/12/2003
00308     Outputs:    -
00309     Purpose:    Polymorphically copies the contents of this node to another
00310     Errors:     An assertion failure will occur if NodeCopy is NULL
00311     Scope:      protected
00312                                      
00313 ***********************************************************************************************/
00314 
00315 void NodeBlendPath::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00316 {
00317     ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00318     ENSURE(IS_A(pNodeCopy, NodeBlendPath), "PolyCopyNodeContents given wrong dest node type");
00319 
00320     if (IS_A(pNodeCopy, NodeBlendPath))
00321         CopyNodeContents((NodeBlendPath*)pNodeCopy);
00322 }
00323 
00324 
00325 
00326 /***********************************************************************************************
00327 
00328 >   virtual void NodeBlendPath::Render(RenderRegion* pRRegion)
00329 
00330     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00331     Created:    29/4/99  
00332     Inputs:     Pointer to a render region
00333     Purpose:    Overrides inherited function to do nothing.
00334                 
00335 
00336 ***********************************************************************************************/
00337 
00338 void NodeBlendPath::Render(RenderRegion* pRender)
00339 {    
00340     
00341     //if (!InsideBlend())
00342         NodePath::Render(pRender);
00343 
00344 }  
00345 
00346 
00347 /********************************************************************************************
00348 
00349 >   virtual void NodeBlendPath::RenderEorDrag( RenderRegion* pRender )
00350 
00351     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00352     Created:    29/4/99
00353     Inputs:     pRender - A Pointer to the current RenderRegion
00354     Purpose:    Overrides inherited function to do nothing.
00355 
00356 ********************************************************************************************/
00357 
00358 void NodeBlendPath::RenderEorDrag( RenderRegion* pRender )
00359 {
00360     //if (!InsideBlend())
00361     BlobManager* pBlobMan = GetApplication()->GetBlobManager();
00362     BlobStyle CurrBlobs = pBlobMan->GetCurrentInterest();
00363     if (CurrBlobs.Object)
00364         NodePath::RenderEorDrag(pRender);
00365 }
00366 
00367 
00368 /********************************************************************************************
00369 
00370 >   virtual void NodeBlendPath::RenderObjectBlobs(RenderRegion* pRender)
00371 
00372     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00373     Created:    29/4/99
00374     Inputs:     pRender - The region to render the blobs into
00375     Purpose:    Draws the paths object blobs into the render region supplied
00376 
00377 ********************************************************************************************/
00378 
00379 void NodeBlendPath::RenderObjectBlobs(RenderRegion* pRender)
00380 {
00381 //  if (Tool::GetCurrentID() == TOOLID_BEZTOOL)
00382         NodePath::RenderObjectBlobs(pRender);
00383 //  else
00384 //  {
00385         // set our eor colour.
00386 //      pRender->SetLineColour(BLACK);
00387         // render the path
00388 //      pRender->DrawPath(&InkPath);
00389         // call the parent class render function
00390 //      NodePath::RenderObjectBlobs(pRender);
00391 //  }
00392 }
00393 
00394 
00395 void NodeBlendPath::RenderBlendBlobs(RenderRegion* pRender)
00396 {
00397     NodePath::RenderObjectBlobs(pRender);
00398 }
00399 
00400 
00401 /********************************************************************************************
00402 
00403 >   DocRect NodeBlendPath::GetBoundingRect(BOOL DontUseAttrs=FALSE, BOOL HitTest=FALSE)
00404 
00405     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00406     Created:    29/4/99
00407     Inputs:     DontUseAttrs - TRUE if you don't want to use the nodes attrs to calculate
00408                 the bounding rect (defaults will be used). Defaults to FALSE.
00409                 HitTest      - TRUE if being called during HitTest
00410     Returns:    A null rectangle
00411     Purpose:    Returns a completely null rectangle
00412 
00413 ********************************************************************************************/
00414 
00415 DocRect NodeBlendPath::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
00416 {
00417     /* Tricky problems:
00418        (1) When importing, the importer translates the imported picture to centre around
00419            the drop point. Unfortunately it calls us to find our bbox. We don't have a
00420            bbox until the moulder nodes are built, which is not until PostImport time so
00421            the importer does a Translate = (Drop - Center) which is X = (0 - C), BAD.
00422            So we must return a bbox if their is no moulder in the mould! Nasty Showstopper fix  */
00423     
00424 /*  if (InsideBlend())
00425     {
00426         // if there is a moulder node to contribute a bbox
00427         if (FindNext(CC_RUNTIME_CLASS(NodeMoulder)))
00428         {
00429             // Then we dont contribute anything!
00430             DocRect Rect;
00431             return Rect;
00432         }
00433     }
00434 */
00435     // Otherwise we do.
00436     return NodePath::GetBoundingRect(DontUseAttrs);
00437 }
00438 
00439 
00440 /********************************************************************************************
00441 
00442 >   BOOL NodeBlendPath::InsideBlend()
00443 
00444     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00445     Created:    29/4/99
00446     Inputs:     -
00447     Returns:    TRUE if this blend path is inside a blend object ie its immediate parent
00448                 is a blend object
00449     Purpose:    Determins whether the immediate parent of this node blend path object is
00450                 a blend object.
00451 
00452 ********************************************************************************************/
00453 
00454 BOOL NodeBlendPath::InsideBlend()
00455 {
00456     Node* p = FindParent();
00457     if (p)
00458     {
00459         if (IS_A(p, NodeBlend))
00460             return TRUE;
00461         if (IS_A(p, NodeHidden))
00462             return TRUE;
00463     }
00464     return FALSE;
00465 }
00466 
00467 
00468 
00469 /*********************************************************************************************
00470 
00471 >    BOOL NodeBlendPath::ExportRender(RenderRegion* pRegion)
00472 
00473      Author:    Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00474      Created:   29/4/99
00475      Inputs:    pRegion = ptr to the export render region to export to
00476      Outputs:   
00477      Returns:   TRUE if ok, FALSE if something went wrong
00478      Purpose:   Called after this node and all of its children have been rendered to the
00479                 export region. This outputs the "end mould" command.
00480                 Supports ArtWorks EPS and Camelot EPS
00481      Errors:    
00482 
00483 **********************************************************************************************/
00484  
00485 BOOL NodeBlendPath::ExportRender(RenderRegion* pRegion) 
00486 {
00487 /*#ifdef DO_EXPORT
00488     if (pRegion->IS_KIND_OF(NativeRenderRegion))
00489         return ExportCAMEPS(pRegion);
00490 
00491     if (pRegion->IS_KIND_OF(ArtWorksEPSRenderRegion))
00492         return ExportAWEPS(pRegion);
00493 #endif  
00494 */
00495     return FALSE;
00496 }
00497 
00498 
00499 /*********************************************************************************************
00500 
00501     BOOL NodeBlendPath::ExportCAMEPS(RenderRegion* pRegion)
00502 
00503     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00504     Created:    29/4/99
00505     Inputs:     pRegion = a pointer to a Camelot EPS render region
00506     Returns:    TRUE if we've rendered the object
00507                 FALSE if we want the caller to render the object
00508     Purpose:    Export delimiter tokens for this particular object.
00509                 The format is defined as
00510                     csmp
00511                         path description
00512                     cemp
00513 
00514 **********************************************************************************************/
00515 
00516 BOOL NodeBlendPath::ExportCAMEPS(RenderRegion* pRegion)
00517 {
00518 /*#ifdef DO_EXPORT
00519     EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
00520 
00521     // If we're hanging around in a mould then export the correct tokens
00522     if (!InsideBlend())
00523     {
00524         NodePath::Render(pRegion);
00525     }
00526     else
00527     {
00528         pDC->OutputToken("csmp");           // Camelot "start mould path" token
00529         pDC->OutputNewLine();
00530 
00531         // Call the parent class
00532         NodePath::Render(pRegion);
00533 
00534         pDC->OutputToken("cemp");           // Camelot "start mould path" token
00535         pDC->OutputNewLine();
00536     }
00537 #endif
00538 */
00539     return TRUE;
00540 }
00541 
00542 
00543 
00544 
00545 /*********************************************************************************************
00546 
00547     BOOL NodeBlendPath::ExportAWEPS(RenderRegion* pRegion)
00548 
00549     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00550     Created:    29/4/99
00551     Inputs:     pRegion = a pointer to a Camelot EPS render region
00552     Returns:    TRUE if we've rendered the object
00553                 FALSE if we want the caller to render the object
00554     Purpose:    Overrides the standard call to Obj->Render so we can render the path
00555                 as we would like
00556 
00557 **********************************************************************************************/
00558 
00559 BOOL NodeBlendPath::ExportAWEPS(RenderRegion* pRegion)
00560 {
00561     // just return false for the moment until we write our
00562     // proper random AWEPS path render function
00563     return FALSE;
00564 }
00565 
00566 
00567 /********************************************************************************************
00568 
00569 >   virtual BOOL NodeBlendPath::AllowOp(ObjChangeParam* pParam,
00570                                         BOOL SetOpPermissionState,
00571                                         BOOL DoPreTriggerEdit = TRUE)
00572 
00573     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 20/01/2000
00574     Created:    29/4/99
00575     Inputs:     pParam - pointer to the change parameter object
00576                 SetOpPermissionState - TRUE to set the Nodes permission flags
00577                 DoPreTriggerEdit     - if TRUE then calls NameGallery::PreTriggerEdit.
00578                                        *Must* be TRUE if the calling Op may make any nodes
00579                                        change their bounds, eg move, line width, cut.
00580                                        Use TRUE if unsure.
00581 
00582     Returns:    TRUE if the operation can proceede, FALSE to stop it
00583     Purpose:    To get node paths inside blend objects to reformat themselves correctly
00584                 when their paths change.
00585     Also see:   NodeBlendPath::OnEdited()
00586 
00587 ********************************************************************************************/
00588 
00589 BOOL NodeBlendPath::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState,
00590                                                     BOOL DoPreTriggerEdit)
00591 {
00592     BOOL ok = TRUE;
00593 
00594     if (SetOpPermissionState)
00595         ok = OnEdited(pParam);
00596 
00597     if (ok) ok = NodePath::AllowOp(pParam,SetOpPermissionState,DoPreTriggerEdit);
00598 
00599     return ok;
00600 }
00601 
00602 
00603 /********************************************************************************************
00604 
00605 >   virtual BOOL NodeBlendPath::OnEdited(ObjChangeParam* pParam)
00606 
00607     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00608     Created:    29/4/99
00609     Inputs:     pParam - pointer to the change parameter object
00610     Returns:    TRUE if ok, FALSE if not
00611     Purpose:    Informs the blend path it has been edited.
00612 
00613                 It records an action that destroys the cached information held by
00614                 this node.
00615     Also see:   NodeBlendPath::AllowOp()
00616 
00617 ********************************************************************************************/
00618 
00619 BOOL NodeBlendPath::OnEdited(ObjChangeParam* pParam)
00620 {
00621     ERROR2IF(pParam == NULL,FALSE,"Null param ptr");
00622 
00623     BOOL ok = TRUE;
00624 
00625     // Always destroy the cached info whenever anyone's doing something to this node.
00626     // When an undoable operation is being performed, this is done by the InitNodeBlendPathAction class
00627     UndoableOperation* pOp=pParam->GetOpPointer();
00628     if (pOp)
00629         ok = (InitNodeBlendPathAction::Init(pOp,pOp->GetUndoActionList(),this)!=AC_FAIL);
00630     else
00631         DestroyCachedInformation();
00632 
00633     return ok;
00634 }
00635 
00636 
00637 
00638 /********************************************************************************************
00639 
00640 >   virtual BOOL NodeBlendPath::DoBecomeA(BecomeA* pBecomeA)
00641 
00642     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00643     Created:    16/10/00
00644     Inputs:     pBecomeA =  ptr to info class containing everything a node needs to be able
00645                             to become something else
00646     Outputs:    -
00647     Returns:    TRUE if successful, FALSE otherwise
00648     Purpose:    Actually tries to change the node into a different node type.
00649                 This responds to BECOMEA_PASSBACK reason by making a duplicate NodeBlendPath and passing
00650                 it to the pfnPassBack func provided in the pBecomeA class.
00651                 This responds to BECOMEA_REPLACE by making a duplicate NodePath (not NodeBlendPath)
00652                 and inserting into the tree.
00653     Errors:     -
00654     SeeAlso:    NodePath::DoBecomeA()
00655 
00656 ********************************************************************************************/
00657 
00658 BOOL NodeBlendPath::DoBecomeA(BecomeA* pBecomeA)
00659 {
00660     // Check for a NULL entry param
00661     ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));
00662 
00663     // This lump checks that the Reason is one that we understand
00664     // It also makes sure that we don't have a NULL UndoOp ptr
00665     BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
00666     ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));
00667 
00668     BOOL Success = TRUE;            // Our success flag (Important that this defaults to TRUE)
00669     NodePath* pNewNodePath = NULL;  // Ptr to a new NodePath, if we get to make one.
00670     
00671     if (pBecomeA->BAPath())
00672     {
00673         switch (pBecomeA->GetReason())
00674         {
00675             case BECOMEA_REPLACE:
00676             {
00677                 // we need to be a NodePath ....
00678 
00679                 // Make a copy of the NodePath of this NodeBlendPath
00680                 CALL_WITH_FAIL(((pNewNodePath = (NodePath*)NodePath::SimpleCopy ()) != NULL), pBecomeA->GetUndoOp(), Success);
00681                 
00682                 if (Success)
00683                 {
00684                     // MUST now copy our children since we need to copy any attributes the path has appllied to it
00685                     CopyChildAttrs (pNewNodePath);
00686                     
00687                     UndoableOperation* pUndoOp = pBecomeA->GetUndoOp();
00688                     // NOT sure if its valid to not have one of these (seems to be assumed in other places)
00689                     // so for now this ERROR2 will fire if there isn't one ....
00690 //                  ERROR2IF(pUndoOp == NULL, FALSE, "No op pointer in NodeBlendPath::DoBecomeA");
00691 
00692                     if (pUndoOp)
00693                     {
00694                         // hide the text story
00695                         NodeHidden* pNodeHidden;
00696                         if (pUndoOp->DoHideNode(this,FALSE,&pNodeHidden)==FALSE)
00697                             Success = FALSE;
00698                         // Insert the NodeGroup next to the old hidden TextStory
00699                         if (!pUndoOp->DoInsertNewNode(pNewNodePath,pNodeHidden,NEXT,FALSE,FALSE,FALSE,FALSE))
00700                             Success = FALSE;
00701                     }
00702                     else
00703                     {
00704                         pNewNodePath->AttachNode(this, NEXT);
00705                     }
00706 
00707                     if (Success)
00708                         pBecomeA->PassBack(pNewNodePath,this);
00709 
00710                     if (!pUndoOp)
00711                     {
00712                         CascadeDelete();
00713                         delete this;
00714                     }
00715                 }
00716             }
00717             break;
00718 
00719             case BECOMEA_PASSBACK :
00720             {
00721                 // we need to be a NodePath ....
00722 
00723                 // Make a copy of the NodePath of this NodeBlendPath
00724                 CALL_WITH_FAIL(((pNewNodePath = (NodePath*)SimpleCopy()) != NULL), pBecomeA->GetUndoOp(), Success);
00725 
00726                 // If successful, pass it back with my attribute map
00727                 if (Success) Success = pBecomeA->PassBack(pNewNodePath,this);
00728             }
00729             break;
00730 
00731             default:
00732                 break;
00733         }
00734     }
00735 
00736     if (!Success)
00737     {
00738         if (pNewNodePath != NULL)
00739         {
00740             // Delete all the NodePath's children (if it has any) and unlink it from the tree (if it's linked)
00741             // This is all done by CascadeDelete()
00742             pNewNodePath->CascadeDelete(); 
00743             delete pNewNodePath;
00744             pNewNodePath = NULL;
00745         }
00746     }
00747 
00748     return Success;
00749 }
00750 
00751 /********************************************************************************************
00752 
00753 >   virtual INT32 NodeBlendPath::ComplexCopy(CopyStage Stage, Range& RangeToCopy, Node** pOutput)
00754 
00755     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00756     Created:    29/4/99
00757     Inputs:     Stage       - COPYOBJECT   if we should make a copy
00758                             - COPYFINISHED once the entire copy operation has completed
00759                 RangeToCopy - Describes the range which is currently being copied.
00760                 pOutput     - a pointer to a pointer to a node. Set this pointer to point
00761                               at the tree copy
00762     Returns:    -1  = The routine failed to make a copy.
00763                  0  = No copy has been made.
00764                 +1  = pOutput points to the copy.
00765     Purpose:    If the copystage is COPYOBJECT,
00766                 The node has been called to copy itself and do what ever it needs to to
00767                 make a sensible copy of other items such as attributes.
00768                 The caller (CopyObjects) will not deep copy this node (as this is a complex
00769                 copy and it expects the handler to know what its doing). In this case the
00770                 NodeBlendPath object needs to turn itself into a node path.
00771     SeeAlso     Node::ComplexCopy(), CopyObjects()
00772 
00773 ********************************************************************************************/
00774 
00775 INT32 NodeBlendPath::ComplexCopy(CopyStage Stage, Range& RangeToCopy, Node** pOutput)
00776 {
00777     ERROR2IF(pOutput==NULL,FALSE,"NodeBlendPath::ComplexCopy() called with NULL output pointer!");
00778 
00779     switch (Stage)
00780     {
00781         case COPYOBJECT:
00782         {   
00783             // we've been asked to make a copy of ourselves
00784             NodePath* NodeCopy = CreateNodePathCopy();
00785             if (NodeCopy != NULL)
00786             {
00787                 (*pOutput) = NodeCopy;
00788                 return 1;
00789             }
00790             break;
00791         }
00792 
00793         case COPYFINISHED:
00794             return 0;
00795             break;
00796     }
00797 
00798     return -1;
00799 }
00800 
00801 /********************************************************************************************
00802 
00803   > NodePath* NodeBlendPath::CreateNodePathCopy()
00804 
00805     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00806     Created:    10/5/99
00807     Inputs:     -
00808     Returns:    ptr to a NodePath equivalent, or NULL if it fails
00809     Purpose:    Creates a NodePath that contains the exact same definition.
00810     SeeAlso:    -
00811 
00812 ********************************************************************************************/
00813 
00814 NodePath* NodeBlendPath::CreateNodePathCopy()
00815 {
00816     // we've been asked to make a copy of ourselves
00817     NodePath* pCopy = new NodePath;
00818     if (pCopy != NULL)
00819         NodePath::CopyNodeContents(pCopy);
00820 
00821     return pCopy;
00822 }
00823 
00824 /********************************************************************************************
00825 
00826   > virtual BOOL NodeBlendPath::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
00827 
00828     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00829     Created:    29/4/99
00830     Inputs:     pFilter = ptr to the filter
00831     Returns:    TRUE if record is written, FALSE if not
00832     Purpose:    Writes the mould path record to the filter
00833     SeeAlso:    -
00834 
00835 ********************************************************************************************/
00836 
00837 BOOL NodeBlendPath::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
00838 {
00839     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
00840 
00841     INT32 NumCoords = InkPath.GetNumCoords();
00842     INT32 RecordSize = sizeof(INT32)+(sizeof(PathVerb)*NumCoords)+(sizeof(DocCoord)*NumCoords);
00843 
00844     CamelotFileRecord Rec(pFilter,TAG_BLEND_PATH,RecordSize);
00845 
00846     BOOL ok = Rec.Init();
00847 
00848     if (ok) ok = Rec.WritePath(&InkPath);
00849     if (ok) ok = pFilter->Write(&Rec);
00850     if (ok)
00851     {
00852         CamelotFileRecord FilledRec(pFilter, TAG_NODEBLENDPATH_FILLED, sizeof(INT32));
00853         
00854         ok = FilledRec.Init();
00855         if (ok)
00856         {
00857             INT32 Filled = InkPath.IsFilled;
00858             ok = FilledRec.WriteINT32(Filled);
00859             if (ok) ok = pFilter->Write(&FilledRec);
00860         }
00861     }
00862     if (!ok)
00863         pFilter->GotError(_R(IDE_FILE_WRITE_ERROR));
00864 
00865     return ok;
00866 }
00867 
00868 //--------------------------------------------------------------
00869 // See NodeBlendPath::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
00870 //
00871 BOOL NodeBlendPath::WritePreChildrenNative(BaseCamelotFilter* pFilter)
00872 {
00873     return WritePreChildrenWeb(pFilter);
00874 }
00875 
00876 
00877 /********************************************************************************************
00878 
00879  > void NodeBlendPath::DestroyCachedInformation()
00880 
00881     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00882     Created:    29/4/99
00883     Inputs:     -
00884     Returns:    -
00885     Purpose:    Destroys any cached information the node may be storing about the path,
00886                 such as it's length.
00887 
00888                 Should be called whenever the node is edited, for example.
00889     SeeAlso:    -
00890 
00891 ********************************************************************************************/
00892 
00893 void NodeBlendPath::DestroyCachedInformation()
00894 {
00895     m_CachedPathLength = -1.0;
00896 
00897     if (m_pCachedPointsAtDistance != NULL)
00898     {
00899         m_pCachedPointsAtDistance->RemoveAll();
00900         delete m_pCachedPointsAtDistance;
00901         m_pCachedPointsAtDistance = NULL;
00902     }
00903 }
00904 
00905 /********************************************************************************************
00906 
00907  > double NodeBlendPath::GetPathLength()
00908 
00909     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00910     Created:    29/4/99
00911     Inputs:     -
00912     Returns:    The length of the path stored in this NodeBlendPath
00913     Purpose:    Access function to underlying Path function
00914                 Also allows the NodeBlendPath to do a bit of caching
00915     SeeAlso:    -
00916 
00917 ********************************************************************************************/
00918 
00919 double NodeBlendPath::GetPathLength()
00920 {
00921     if (m_CachedPathLength < 0)
00922         m_CachedPathLength = InkPath.GetPathLength();
00923     
00924     return m_CachedPathLength;
00925 }
00926 
00927 /********************************************************************************************
00928 >   BOOL NodeBlendPath::GetPointAtDistance(MILLIPOINT Distance, DocCoord* pPoint)
00929 
00930     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00931     Created:    30/4/99
00932     Inputs:     Distance = a length along the path
00933     Outputs:    pPoint = the coordinate of the point that distance along the path
00934                 pTangent = tangent at this point (can be NULL)
00935     Returns:    TRUE/FALSE for success/failure
00936     Purpose:    Gets the coordinate of a point a certain distance along this path
00937                 Calls the underlying Path class function
00938 
00939                 This wrapper allows us to do any caching, if we get round to it.
00940 ********************************************************************************************/
00941 
00942 BOOL NodeBlendPath::GetPointAtDistance(MILLIPOINT Distance, DocCoord* pPoint, double* pTangent)
00943 {
00944     ERROR2IF(pPoint == NULL,FALSE,"NULL pPoint param");
00945 
00946     BOOL Found = FALSE;
00947 
00948 #ifdef NBP_CACHEPOINTATDISTANCE
00949     CPathPointInfo  PointInfo;
00950 
00951     if (m_pCachedPointsAtDistance == NULL)
00952     {
00953         m_pCachedPointsAtDistance = new CMap<MILLIPOINT,MILLIPOINT&,CPathPointInfo,CPathPointInfo&>;
00954 //      if (m_pCachedPointsAtDistance != NULL)
00955 //          m_pCachedPointsAtDistance->InitHashTable(1277);     // Init hash table size to a suitably large prime number
00956     }
00957 
00958     if (m_pCachedPointsAtDistance != NULL)
00959     {
00960         Found = m_pCachedPointsAtDistance->Lookup(Distance,PointInfo);
00961         //if (Found)
00962     //  TRACEUSER( "Diccon", _T("Point %d, %d found in cache\n"), PointInfo.m_Point.x, PointInfo.m_Point.y);
00963 
00964     }
00965 
00966     if (!Found)
00967     {
00968         if (InkPath.GetPointAtDistance(Distance,&PointInfo.m_Point,&PointInfo.m_Tangent))
00969         {
00970             if (m_pCachedPointsAtDistance != NULL)
00971                 m_pCachedPointsAtDistance->SetAt(Distance,PointInfo);
00972     //      TRACEUSER( "Diccon", _T("Point %d, %d found from line\n"), PointInfo.m_Point.x, PointInfo.m_Point.y);
00973             Found = TRUE;
00974         }
00975     }
00976 
00977     if (Found)
00978     {
00979         *pPoint = PointInfo.m_Point;
00980         if (pTangent)
00981             *pTangent = PointInfo.m_Tangent;
00982     }
00983 #else
00984     double Tangent = 0.0;
00985     if (InkPath.GetPointAtDistance(Distance,pPoint,&Tangent))
00986     {
00987         if (pTangent)
00988             *pTangent = Tangent;
00989 
00990         Found = TRUE;
00991     }
00992 #endif // NBP_CACHEPOINTATDISTANCE
00993 
00994 //  if (Found == FALSE)
00995     //  TRACEUSER( "Diccon", _T("Not found at distance %d\n"), Distance);
00996     return Found;
00997 }
00998 
00999 
01000 
01001 /********************************************************************************************
01002 
01003  > UINT32 NodeBlendPath::GetPathIndex()
01004 
01005     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01006     Created:    23/9/99
01007     Inputs:     -
01008     Returns:    The index number of this nodeblendpath
01009     Purpose:    To find out which NBP this is.
01010     SeeAlso:    -
01011 
01012 ********************************************************************************************/
01013 
01014 UINT32 NodeBlendPath::GetPathIndex()
01015 {
01016     return m_Index;
01017 }
01018 
01019 
01020 
01021 /********************************************************************************************
01022 
01023  > INT32 NodeBlendPath::SetPathIndex()
01024 
01025     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01026     Created:    23/9/99
01027     Inputs:     -
01028     Returns:    The index number of this nodeblendpath, or -1 if it fails
01029     Purpose:    Sets the index of this NBP by finding out how many NBP's already 
01030                 exist in the parent nodeblend
01031     SeeAlso:    -
01032 
01033 ********************************************************************************************/
01034 
01035 INT32 NodeBlendPath::SetPathIndex()
01036 {
01037     Node* pParent = ((Node*)this)->FindParent();
01038     if ((pParent == NULL) || (!pParent->IS_KIND_OF(NodeBlend)))
01039     {
01040         ERROR3("Path has no parent, or it is not a nodeblend");
01041         return -1;
01042     }
01043     
01044     UINT32 Index = ((NodeBlend*)pParent)->GetNumNodeBlendPaths();
01045 
01046     m_Index = Index;
01047 
01048     return (INT32)Index;
01049 }
01050 
01051 
01052 /***********************************************************************************************
01053 
01054 >   virtual BOOL NodeBlendPath::IsANodeBlendPath()
01055 
01056     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01057     Created:    14/11/99
01058     Inputs:     -
01059     Purpose:    virtual identifier function
01060     
01061 
01062 ***********************************************************************************************/
01063 
01064 BOOL NodeBlendPath::IsANodeBlendPath()
01065 {
01066     return TRUE;
01067 }
01068 
01069 //------------------------------------------------------------------------------------------
01070 //------------------------------------------------------------------------------------------
01071 //------------------------------------------------------------------------------------------
01072 
01073 /********************************************************************************************
01074 
01075 >   ActionCode InitNodeBlendPathAction::Init(UndoableOperation* pOp,ActionList* pActionList,NodeBlend* pThisNodeBlend)
01076 
01077     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01078     Created:    4/5/99
01079     Inputs:     pOp             = ptr to the operation to which this action belongs
01080                 pNodeBlendPath  = ptr to blend path node involved
01081                 pActionList     = ptr to action list to which this action should be added
01082     Outputs:    -
01083     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
01084     Purpose:    Simply destroys the cached information for this blend path
01085     Errors:     -
01086     SeeAlso:    Action::Init()
01087 
01088 ********************************************************************************************/
01089 
01090 ActionCode InitNodeBlendPathAction::Init(UndoableOperation* pOp,ActionList* pActionList,NodeBlendPath* pNodeBlendPath)
01091 {
01092     ERROR2IF(pOp            == NULL,AC_FAIL,"No undo op ptr given");
01093     ERROR2IF(pActionList    == NULL,AC_FAIL,"No action list given");
01094     ERROR2IF(pNodeBlendPath == NULL,AC_FAIL,"No blend path node given");
01095 
01096     UINT32 ActSize = sizeof(InitNodeBlendPathAction);
01097     InitNodeBlendPathAction* pNewAction;
01098     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(InitNodeBlendPathAction),(Action**)&pNewAction);
01099 
01100     if (Ac != AC_FAIL && pNewAction != NULL)
01101     {
01102         pNewAction->m_pNodeBlendPath = pNodeBlendPath;
01103         pNodeBlendPath->DestroyCachedInformation();
01104     }
01105 
01106     return Ac;
01107 }
01108 
01109 /********************************************************************************************
01110 
01111 >   ActionCode InitNodeBlendPathAction::Execute();
01112 
01113     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01114     Created:    4/5/99
01115     Inputs:     -
01116     Outputs:    -
01117     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
01118     Purpose:    Executes the action.  
01119                 Destroys the blend path node's cached info
01120     Errors:     -
01121     SeeAlso:    Action::Init()
01122 
01123 ********************************************************************************************/
01124 
01125 ActionCode InitNodeBlendPathAction::Execute()
01126 {
01127     if (pOperation->IS_KIND_OF(UndoableOperation))
01128         return InitNodeBlendPathAction::Init((UndoableOperation*)pOperation,pOppositeActLst,m_pNodeBlendPath);
01129     else
01130     {
01131         ERROR3("InitNodeBlendPathAction::Execute() called with op that's not an undoable op");
01132         return AC_FAIL;
01133     }
01134 }
01135 

Generated on Sat Nov 10 03:45:48 2007 for Camelot by  doxygen 1.4.4