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