00001 // $Id: nodebrsh.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 // implementation of the NodeBrush class 00100 #include "camtypes.h" 00101 #include "nodebrsh.h" 00102 //#include "group.h" 00103 //#include "rndrgn.h" 00104 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 #include "blobs.h" 00107 //#include "nodershp.h" 00108 #include "ndbrshpt.h" 00109 #include "ndbrshmk.h" 00110 //#include "progress.h" 00111 //#include "objchge.h" 00112 //#include "markn.h" 00113 //#include "opdrbrsh.h" 00114 #include "opshadow.h" 00115 //#include "opbevel.h" 00116 #include "objchge.h" 00117 00118 class BlendRef; 00119 00120 CC_IMPLEMENT_DYNCREATE(NodeBrush, NodeGroup); 00121 // Declare smart memory handling in Debug builds 00122 #define new CAM_DEBUG_NEW 00123 #define BRUSH_MIN_SPACING 100 00124 #define BRUSH_MAX_SPACING 10000000 00125 #define BRUSH_DEFAULT_SPACING 10000 00126 00127 00128 /********************************************************************************************* 00129 00130 > NodeBrush::NodeBrush() 00131 00132 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00133 Created: 6/10/99 00134 Inputs: 00135 Outputs: 00136 Returns: 00137 Purpose: This constructor creates a NodeBrush linked to no other 00138 Errors: 00139 00140 **********************************************************************************************/ 00141 00142 NodeBrush::NodeBrush(): NodeGroup() 00143 { 00144 00145 } 00146 00147 /*********************************************************************************************** 00148 00149 > void NodeBrush::NodeBrush 00150 ( 00151 Node* ContextNode, 00152 AttachNodeDirection Direction, 00153 BOOL Locked = FALSE, 00154 BOOL Mangled = FALSE, 00155 BOOL Marked = FALSE, 00156 BOOL Selected = FALSE, 00157 ) 00158 00159 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00160 Created: 6/10/99 00161 Inputs: ContextNode: Pointer to a node which this node is to be attached to. 00162 00163 Direction: 00164 00165 Specifies the direction in which this node is to be attached to the 00166 ContextNode. The values this variable can take are as follows: 00167 00168 PREV : Attach node as a previous sibling of the context node 00169 NEXT : Attach node as a next sibling of the context node 00170 FIRSTCHILD: Attach node as the first child of the context node 00171 LASTCHILD : Attach node as a last child of the context node 00172 00173 The remaining inputs specify the status of the node: 00174 00175 Locked: Is node locked ? 00176 Mangled: Is node mangled ? 00177 Marked: Is node marked ? 00178 Selected: Is node selected ? 00179 00180 Outputs: - 00181 Returns: - 00182 Purpose: This method initialises the node and links it to ContextNode in the 00183 direction specified by Direction. All necessary tree links are 00184 updated. 00185 00186 Errors: An assertion error will occur if ContextNode is NULL 00187 00188 00189 ***********************************************************************************************/ 00190 00191 NodeBrush::NodeBrush(Node* ContextNode, 00192 AttachNodeDirection Direction, 00193 BOOL Locked, 00194 BOOL Mangled, 00195 BOOL Marked, 00196 BOOL Selected 00197 ):NodeGroup(ContextNode, Direction, Locked, Mangled, Marked, 00198 Selected) 00199 { 00200 00201 00202 } 00203 00204 00205 /********************************************************************************************* 00206 00207 > NodeBrush::~NodeBrush() 00208 00209 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00210 Created: 6/10/99 00211 Inputs: 00212 Outputs: 00213 Returns: 00214 Purpose: Destructor 00215 Errors: 00216 00217 **********************************************************************************************/ 00218 00219 00220 NodeBrush::~NodeBrush() 00221 { 00222 00223 00224 } 00225 00226 /******************************************************************************************** 00227 00228 > DocRect NodeBrush::GetBlobBoundingRect() 00229 00230 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00231 Created: 7/10/99 00232 Returns: DocRect - The bounding rect of the node and its blobs 00233 Purpose: This calls the base classes GetBlobBoundingRect(), and inflates the result by the width 00234 of a blob 00235 00236 ********************************************************************************************/ 00237 00238 DocRect NodeBrush::GetBlobBoundingRect() 00239 { 00240 00241 #if !defined(EXCLUDE_FROM_RALPH) 00242 // Find the base class blob bounding rectangle 00243 DocRect Rect = NodeGroup::GetBlobBoundingRect(); 00244 00245 // inflate it by the width of a blob (plus a bit) 00246 DocRect TempRect; 00247 GetApplication()->GetBlobManager()->GetBlobRect(Rect.lo,&TempRect); 00248 INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*1)/1; 00249 Rect.Inflate(Delta); 00250 00251 return Rect; 00252 #else 00253 return DocRect(0,0,0,0); 00254 #endif 00255 00256 } 00257 00258 /******************************************************************************************** 00259 00260 > DocRect NodeBrusher::GetBoundingRect(BOOL DontUseAttrs=FALSE, BOOL HitTest=FALSE) 00261 00262 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00263 Created: 11/10/94 00264 Inputs: DontUseAttrs - TRUE if we should ignore the nodes attributes. 00265 Defaults to FALSE 00266 HitTest - TRUE if being called during HitTest 00267 Returns: The nodes bounding rect 00268 Purpose: if the bounding rect is valid it is returned, if not, it is recalculated 00269 and then returned. 00270 SeeAlso: NodeBrusher::GetBlobBoundingRect 00271 00272 ********************************************************************************************/ 00273 00274 00275 DocRect NodeBrush::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest) 00276 { 00277 /* 00278 // first get the bounding rect of the path 00279 DocRect Rect = m_pNodeBrushPath->GetBoundingRect(); 00280 00281 // inflate by half the size of the brush ink object. 00282 00283 NodeRenderableInk* pInk = m_pNodeBrushMaker->GetInkNode(); 00284 00285 if (pInk != NULL) 00286 { 00287 DocRect InkRect = pInk->GetBoundingRect(); 00288 00289 INT32 dx = InkRect.Width() / 2; 00290 INT32 dy = InkRect.Height() / 2; 00291 00292 Rect.Inflate(dx, dy); 00293 } 00294 00295 return Rect; 00296 */ 00297 // default docrect constructor makes empty rect 00298 DocRect Rect; 00299 if (m_pNodeBrushMaker != NULL) 00300 Rect = m_pNodeBrushMaker->GetBoundingRect(); 00301 00302 return Rect; 00303 } 00304 00305 00306 00307 /******************************************************************************************** 00308 00309 > void NodeBrush::Render (RenderRegion* pRender) 00310 00311 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00312 Created: 7/10/99 00313 Inputs: pRender - The region to draw the blobs in 00314 Purpose: Renders the nodebrushpath, if selected, otherwise nothing. The main 00315 rendering is performed by the nodebrushmaker 00316 00317 ********************************************************************************************/ 00318 00319 void NodeBrush::Render(RenderRegion* pRender) 00320 { 00321 if (this->IsSelected()) 00322 { 00323 if (m_pNodeBrushPath != NULL) 00324 m_pNodeBrushPath->RenderObjectBlobs(pRender); 00325 } 00326 if (m_pNodeBrushMaker != NULL) 00327 m_pNodeBrushMaker->Render(pRender); 00328 } 00329 00330 00331 /******************************************************************************************** 00332 > virtual SubtreeRenderState NodeBrush::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip = TRUE) 00333 00334 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00335 Created: 22/06/2004 00336 Inputs: A Render Region to Render into. 00337 Returns: PRE_FAILED for something went wrong, 00338 PRE_RENDER_CHILDREN for continue to render children, 00339 PRE_NO_RENDER_CHILDREN for DO NOT Render any of my children!!!! 00340 00341 Purpose: Enables Nodes to be able to Do Pre Print time alterations or even take over 00342 the control of the current Printing of their children. 00343 00344 ********************************************************************************************/ 00345 SubtreeRenderState NodeBrush::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip) 00346 { 00347 return SUBTREE_ROOTONLY; 00348 } 00349 00350 00351 00352 00353 /******************************************************************************************** 00354 00355 > void NodeBrush::RenderObjectBlobs(RenderRegion* pRender) 00356 00357 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00358 Created: 7/10/99 00359 Inputs: pRender - The region to draw the blobs in 00360 Purpose: Renders the object blobs 00361 00362 ********************************************************************************************/ 00363 00364 void NodeBrush::RenderObjectBlobs(RenderRegion* pRegion) 00365 { 00366 #if !defined(EXCLUDE_FROM_RALPH) 00367 // Find out about the groups bounding rect 00368 DocRect BoundingRect = GetBoundingRect(); 00369 00370 // Inflate the bounds by the width of a blob 00371 DocRect TempRect; 00372 GetApplication()->GetBlobManager()->GetBlobRect(BoundingRect.lo,&TempRect); 00373 INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*3)/4; 00374 BoundingRect.Inflate(Delta); 00375 00376 // Find out where to draw the blobs 00377 DocCoord Low = BoundingRect.LowCorner(); 00378 DocCoord High = BoundingRect.HighCorner(); 00379 00380 // Set the colours of the blobs 00381 pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB); 00382 pRegion->SetLineColour(COLOUR_NONE); 00383 00384 // Draw all the blobs 00385 pRegion->DrawBlob(Low, BT_UNSELECTED); 00386 pRegion->DrawBlob(High, BT_UNSELECTED); 00387 pRegion->DrawBlob(DocCoord(Low.x, High.y), BT_UNSELECTED); 00388 pRegion->DrawBlob(DocCoord(High.x, Low.y), BT_UNSELECTED); 00389 00390 // for some reason the NBP is never called, there is probably a 00391 // proper fix for this but I don't have time right now, so render 00392 // the nodeblend path here 00393 m_pNodeBrushPath->RenderObjectBlobs(pRegion); 00394 00395 00396 #endif 00397 } 00398 00399 00400 /******************************************************************************************** 00401 00402 > void NodeBrush::RenderTinyBlobs(RenderRegion* pRender) 00403 00404 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00405 Created: 7/10/99 00406 Inputs: pRender - The region to draw the blobs in 00407 Purpose: Renders the object blobs 00408 00409 ********************************************************************************************/ 00410 00411 void NodeBrush::RenderTinyBlobs(RenderRegion* pRegion) 00412 { 00413 // for some reason the NBP is never called, there is probably a 00414 // proper fix for this but I don't have time right now, so render 00415 // the nodeblend path here 00416 m_pNodeBrushPath->RenderTinyBlobs(pRegion); 00417 00418 } 00419 00420 00421 /******************************************************************************************** 00422 00423 > void NodeBrush::Transform(TransformBase& Trans) 00424 00425 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00426 Created: 7/10/99 00427 Inputs: Trans - the transformation to perform 00428 Purpose: transforms the brush 00429 00430 ********************************************************************************************/ 00431 00432 void NodeBrush::Transform(TransformBase& Trans) 00433 { 00434 // The groups bounding rect is no longer valid 00435 InvalidateBoundingRect(); 00436 00437 // Transform all the children 00438 // See GroupCanTransformCached() 00439 NodeGroup::Transform(Trans); 00440 00441 } 00442 00443 00444 00445 /******************************************************************************************** 00446 00447 > virtual BOOL NodeBrush::WritePreChildrenWeb(BaseCamelotFilter* pFilter) 00448 00449 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00450 Created: 7/20/99 00451 Inputs: pFilter = ptr to the filter 00452 Returns: TRUE if record is written, FALSE if not 00453 Purpose: Writes the brush record to the filter 00454 00455 SeeAlso: - 00456 00457 ********************************************************************************************/ 00458 00459 BOOL NodeBrush::WritePreChildrenWeb(BaseCamelotFilter* pFilter) 00460 { 00461 return TRUE; 00462 } 00463 00464 00465 /******************************************************************************************** 00466 00467 > virtual BOOL NodeBrush::WritePreChildrenNative(BaseCamelotFilter* pFilter) 00468 00469 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00470 Created: 7/20/99 00471 Inputs: pFilter = ptr to the filter 00472 Returns: TRUE if record is written, FALSE if not 00473 Purpose: Writes the brush record to the filter 00474 00475 SeeAlso: - 00476 00477 ********************************************************************************************/ 00478 00479 BOOL NodeBrush::WritePreChildrenNative(BaseCamelotFilter* pFilter) 00480 { 00481 return TRUE; 00482 } 00483 00484 00485 00486 /*********************************************************************************************** 00487 00488 > Node* NodeBrush::SimpleCopy() 00489 00490 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00491 Created: 6/10/99 00492 Inputs: - 00493 Outputs: - 00494 Returns: A copy of the node, or NULL if memory has run out 00495 00496 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 00497 The function is virtual, and must be defined for all derived classes. 00498 00499 Errors: If memory runs out when trying to copy, then ERROR is called with an out of memory 00500 error and the function returns NULL. 00501 00502 **********************************************************************************************/ 00503 00504 Node* NodeBrush::SimpleCopy() 00505 { 00506 NodeBrush* pCopyOfNode = new NodeBrush(); 00507 if (pCopyOfNode != NULL) 00508 CopyNodeContents(pCopyOfNode); 00509 return (pCopyOfNode); 00510 } 00511 00512 /*********************************************************************************************** 00513 00514 > void NodeBrush::CopyNodeContents(Node* pCopyOfNode) 00515 00516 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00517 Created: 6/10/99 00518 Inputs: pCopyOfNode - The node to copy data to 00519 Outputs: - 00520 Returns: - 00521 Purpose: Copies the data from this node to pCopyOfNode by first calling the base class to get it to 00522 copy its stuff, and then copying its own stuff 00523 Scope: protected 00524 SeeAlso: NodeGroup::CopyNodeContents 00525 00526 ***********************************************************************************************/ 00527 00528 void NodeBrush::CopyNodeContents(NodeBrush* pCopyOfNode) 00529 { 00530 NodeGroup::CopyNodeContents(pCopyOfNode); 00531 00532 // Copy member vars here 00533 00534 } 00535 00536 00537 00538 /*********************************************************************************************** 00539 > void NodeBrush::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00540 00541 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00542 Created: 18/12/2003 00543 Outputs: - 00544 Purpose: Polymorphically copies the contents of this node to another 00545 Errors: An assertion failure will occur if NodeCopy is NULL 00546 Scope: protected 00547 00548 ***********************************************************************************************/ 00549 00550 void NodeBrush::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00551 { 00552 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 00553 ENSURE(IS_A(pNodeCopy, NodeBrush), "PolyCopyNodeContents given wrong dest node type"); 00554 00555 if (IS_A(pNodeCopy, NodeBrush)) 00556 CopyNodeContents((NodeBrush*)pNodeCopy); 00557 } 00558 00559 00560 00561 /******************************************************************************************** 00562 00563 > virtual String NodeBrush::Describe(BOOL Plural, BOOL Verbose = TRUE) 00564 00565 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00566 Created: 6/10/99 00567 Inputs: Plural: Flag indicating if the string description should be plural or 00568 singular. 00569 Outputs: - 00570 Retuns: Description of the blend node 00571 Purpose: To return a description of the Brush object in either the singular or the 00572 plural. This method is called by the DescribeRange method. 00573 00574 The description will always begin with a lower case letter. 00575 00576 Errors: - 00577 SeeAlso: - 00578 00579 ********************************************************************************************/ 00580 00581 String NodeBrush::Describe(BOOL Plural, BOOL Verbose) 00582 { 00583 return m_BrushName; 00584 } 00585 00586 00587 /********************************************************************************************* 00588 00589 > NodeBrushPath* NodeBrush::GetNodeBtushPath() 00590 00591 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00592 Created: 6/10/99 00593 Inputs: 00594 Outputs: 00595 Returns: the nodebrushpath used by this brush 00596 Purpose: as above 00597 **********************************************************************************************/ 00598 00599 NodeBrushPath* NodeBrush::GetNodeBrushPath() 00600 { 00601 return m_pNodeBrushPath; 00602 } 00603 00604 00605 00606 /********************************************************************************************* 00607 00608 > void NodeBrush: SetNodeBrushPath() 00609 00610 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00611 Created: 6/10/99 00612 Inputs: 00613 Outputs: 00614 Returns: the nodebrushpath used by this brush 00615 Purpose: as above 00616 **********************************************************************************************/ 00617 00618 void NodeBrush::SetNodeBrushPath(NodeBrushPath* pPath) 00619 { 00620 m_pNodeBrushPath = pPath; 00621 00622 } 00623 00624 00625 00626 /********************************************************************************************* 00627 00628 > NodeBrushMaker* NodeBrush::GetNodeBtushMaker() 00629 00630 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00631 Created: 6/10/99 00632 Inputs: 00633 Outputs: 00634 Returns: the nodebrushMaker used by this brush 00635 Purpose: as above 00636 **********************************************************************************************/ 00637 00638 NodeBrushMaker* NodeBrush::GetNodeBrushMaker() 00639 { 00640 return m_pNodeBrushMaker; 00641 } 00642 00643 00644 00645 /********************************************************************************************* 00646 00647 > void NodeBrush: SetNodeBrushMaker() 00648 00649 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00650 Created: 6/10/99 00651 Inputs: 00652 Outputs: 00653 Returns: the nodebrushMaker used by this brush 00654 Purpose: as above 00655 **********************************************************************************************/ 00656 00657 void NodeBrush::SetNodeBrushMaker(NodeBrushMaker* pMaker) 00658 { 00659 m_pNodeBrushMaker = pMaker; 00660 00661 } 00662 00663 /********************************************************************************************* 00664 00665 > MILLIPOINT NodeBrush: GetBrushSpacing() 00666 00667 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00668 Created: 19/11/99 00669 Inputs: 00670 Outputs: 00671 Returns: the spacing between objects of this brush 00672 Purpose: as above 00673 **********************************************************************************************/ 00674 00675 MILLIPOINT NodeBrush::GetBrushSpacing() 00676 { 00677 if (m_pNodeBrushMaker != NULL) 00678 return m_pNodeBrushMaker->GetBrushSpacing(); 00679 else 00680 { 00681 ERROR3("NodeBrushMaker is NULL"); 00682 return 0; 00683 } 00684 } 00685 00686 /********************************************************************************************* 00687 00688 > void NodeBrush: SetBrushSpacing(MILLIPOINT Spacing) 00689 00690 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00691 Created: 18/11/99 00692 Inputs: Spacing to set 00693 Outputs: 00694 Returns: - 00695 Purpose: Sets the distance between brush objects used buy the nodebrushmaker 00696 **********************************************************************************************/ 00697 00698 void NodeBrush::SetBrushSpacing(MILLIPOINT Spacing) 00699 { 00700 if (Spacing >= BRUSH_MIN_SPACING && Spacing >= BRUSH_MAX_SPACING) 00701 { 00702 ERROR3("Invalid spacing got passed to NodeBrush::SetBrushSpacing"); 00703 Spacing = BRUSH_DEFAULT_SPACING; 00704 } 00705 00706 if (m_pNodeBrushMaker != NULL) 00707 { 00708 m_pNodeBrushMaker->SetBrushSpacing(Spacing); 00709 } 00710 else 00711 ERROR3("NodeBrushMaker is NULL"); 00712 00713 } 00714 00715 /******************************************************************************************** 00716 00717 > BOOL NodeBrush::ResetBrushPath() 00718 00719 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00720 Created: 6/10/99 00721 Inputs: - 00722 Outputs: - 00723 Returns: TRUE if successful, FALSE otherwise 00724 Purpose: Asks the nodebrushmaker to recalculate its number of steps, for use when 00725 the nodebrushpath has been edited 00726 00727 ********************************************************************************************/ 00728 00729 BOOL NodeBrush::ResetBrushPath() 00730 { 00731 // get the brushmaker to recalculate how many steps it needs 00732 if (m_pNodeBrushMaker != NULL) 00733 { 00734 m_pNodeBrushMaker->RecalculateMaxStep(); 00735 m_pNodeBrushMaker->ClearListOfPointsToRender(); 00736 } 00737 else 00738 { 00739 ERROR3("NodeBrushMaker is NULL"); 00740 return FALSE; 00741 } 00742 return TRUE; 00743 00744 } 00745 00746 /******************************************************************************************** 00747 00748 > BOOL NodeBrush::ReInitialiseInk() 00749 00750 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00751 Created: 6/10/99 00752 Inputs: - 00753 Outputs: - 00754 Returns: TRUE if successful, FALSE otherwise 00755 Purpose: Asks the nodebrushmaker to reinitialise itself, for use when the ink node has 00756 been altered, e.g. attribute changes. Note that this must be called AFTER the 00757 attribute change in order to work. 00758 00759 ********************************************************************************************/ 00760 00761 BOOL NodeBrush::ReInitialiseInk() 00762 { 00763 if (m_pNodeBrushMaker!= NULL) 00764 { 00765 NodeRenderableInk* pInk = m_pNodeBrushMaker->GetInkNode(); 00766 if (pInk != NULL) 00767 { 00768 //if (!m_pNodeBrushMaker->InitialiseInk(pInk)) 00769 // return FALSE; 00770 //else 00771 { 00772 // clear the cache in case we have any points left to render 00773 m_pNodeBrushMaker->ClearListOfPointsToRender(); 00774 return TRUE; 00775 } 00776 } 00777 00778 } 00779 ERROR3("NodeBrushMaker is NULL"); 00780 return FALSE; 00781 00782 } 00783 00784 /******************************************************************************************** 00785 00786 > void NodeBrush::ChangeNodeBrushPath(NodeBrushPath * pNewPath) 00787 00788 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00789 Created: 6/10/99 00790 Inputs: pNewPath - the new path to set 00791 Outputs: - 00792 Returns: TRUE if successful, FALSE otherwise 00793 Purpose: Changes the nodebrushpath used by the brush 00794 00795 ********************************************************************************************/ 00796 00797 /* IMPLEMENTATION NOTE: 00798 This function was written for use when the path was modified using the freehand or bezier tool. 00799 These operations take care of hiding the old nodebrushpath for you, so it is not performed here. 00800 If you wish to use this function for some other purpose then make sure you do something with 00801 the original nodebrushpath before swapping in a new one 00802 */ 00803 00804 BOOL NodeBrush::ChangeNodeBrushPath(NodeBrushPath* pNewPath) 00805 { 00806 if (pNewPath == NULL) 00807 { 00808 ERROR3("NodeBrushPath is NULL"); 00809 return FALSE;; 00810 } 00811 00812 m_pNodeBrushPath = pNewPath; 00813 if (m_pNodeBrushMaker != NULL) 00814 m_pNodeBrushMaker->InitialisePath(pNewPath); 00815 else 00816 { 00817 ERROR3("NodeBrushMaker is NULL"); 00818 return FALSE;; 00819 } 00820 return TRUE; 00821 } 00822 00823 00824 /********************************************************************************************* 00825 00826 > Node* NodeBrush::HasEditableChild(CCRuntimeClass* ChildClass, Node* pPreviousChild) 00827 00828 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00829 Created: 19/11/99 00830 Inputs: ChildClass = the runtime class of the editable object 00831 pPreviousChild = a pointer to the previous editable child 00832 returned by 'this' node, NULL if this is the first 00833 call to this node. 00834 Outputs: - 00835 Returns: A node pointer, to an object which forms part of the editable surface of 00836 its parent (this node). 00837 Purpose: This function returns our edit node (the NodeBrushPath) 00838 00839 **********************************************************************************************/ 00840 00841 Node* NodeBrush::HasEditableChild(CCRuntimeClass* ChildClass, Node* pPreviousChild) 00842 { 00843 if (ChildClass != CC_RUNTIME_CLASS(NodePath)) 00844 return NULL; 00845 00846 NodeBrushPath* pNodeBrushPath = GetNodeBrushPath(); 00847 // check to see if this has already been asked for once 00848 if (((Node*)pNodeBrushPath) == pPreviousChild) 00849 return NULL; 00850 00851 return pNodeBrushPath; 00852 } 00853 00854 00855 /********************************************************************************************* 00856 00857 > NodeRenderableInk* NodeBrush: GetInkNode() 00858 00859 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00860 Created: 19/11/99 00861 Inputs: 00862 Outputs: 00863 Returns: the ink node used by the nodebrushmaker to generate the blendpaths 00864 Purpose: as above 00865 **********************************************************************************************/ 00866 00867 NodeRenderableInk* NodeBrush::GetInkNode() 00868 { 00869 if (m_pNodeBrushMaker != NULL) 00870 { 00871 return m_pNodeBrushMaker->GetInkNode(); 00872 } 00873 return NULL; 00874 } 00875 00876 00877 00878 /******************************************************************************************** 00879 00880 > virtual BOOL NodeBrush::AllowOp(ObjChangeParam* pParam,BOOL SetOpPermissionState = TRUE) 00881 00882 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00883 Created: 6/12/99 00884 Inputs: pParam = describes the way an op wants to change the node 00885 SetOpPermissionState = if TRUE the Op permission state of this node will be set according to 00886 the outcome of the call 00887 Outputs: - 00888 Returns: TRUE means the node and all its parents are happy with this op, FALSE means don't do it 00889 Purpose: In this instance, the func gives the brush a chance to stop an op from happening to one 00890 of its children. 00891 Currently the only permitted ops on children are those that change their appearance, .eg. 00892 change fill, line width etc. 00893 00894 This must be called *before* the op is performed. 00895 SeeAlso: Node::AllowOp(),GetOpPermission(),SetOpPermission(); 00896 00897 ********************************************************************************************/ 00898 00899 BOOL NodeBrush::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState) 00900 { 00901 ERROR2IF(pParam==NULL,FALSE,"NodeBlend::AllowOp() - pParam==NULL"); 00902 00903 // clean out the calling-child ptr, so it doesn't get passed around unintentionally. 00904 pParam->SetCallingChild(NULL); 00905 00906 // decide if we allow it ... (and if we'll still exist after the op) 00907 BOOL allowed=TRUE; 00908 ObjChangeFlags Flags=pParam->GetChangeFlags(); 00909 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD) 00910 { 00911 if (Flags.DeleteNode || Flags.MultiReplaceNode || Flags.MoveNode) 00912 { 00913 pParam->SetReasonForDenial(_R(IDS_BLEND_CANT_OP_ON_CHILDREN)); 00914 allowed=FALSE; 00915 } 00916 } 00917 00918 // if we allow it, (and our parents weren't calling us) see if our parents do ... 00919 if (allowed && pParam->GetDirection()!=OBJCHANGE_CALLEDBYPARENT && Parent!=NULL) 00920 { 00921 ObjChangeDirection OldDirection=pParam->GetDirection(); 00922 pParam->SetCallingChild(this); 00923 pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD); 00924 allowed=Parent->AllowOp(pParam,SetOpPermissionState); 00925 pParam->SetDirection(OldDirection); 00926 } 00927 00928 if (allowed && pParam->GetDirection() == OBJCHANGE_CALLEDBYCHILD) 00929 { 00930 if (pParam->GetOpPointer()) 00931 { 00932 if (pParam->GetOpPointer()->IS_KIND_OF(OpApplyShadow)) 00933 { 00934 allowed = FALSE; 00935 } 00936 00937 PORTNOTE("other", "Removed use of OpCreateBevel from NodeBrush::AllowOp") 00938 #if !defined(EXCLUDE_FROM_XARALX) 00939 if (pParam->GetOpPointer()->IS_KIND_OF(OpCreateBevel)) 00940 { 00941 allowed = FALSE; 00942 } 00943 #endif 00944 } 00945 } 00946 00947 // if setting permisions ... (and possibly cause post-op code to be called) 00948 if (SetOpPermissionState) 00949 { 00950 if (allowed) 00951 { 00952 if (Parent!=NULL) 00953 Parent->SetOpPermission(PERMISSION_ALLOWED); 00954 00955 // if post process required, ensure our OnChildChange is called (by setting permission on ourself), 00956 // insert an inverse action in the undo 00957 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD || Flags.Attribute) 00958 { 00959 SetOpPermission(PERMISSION_ALLOWED); 00960 PORTNOTE("other", "Removed use of ChangeBrushOpParam from NodeBrush::AllowOp") 00961 #if !defined(EXCLUDE_FROM_XARALX) 00962 UndoableOperation* pOp=pParam->GetOpPointer(); 00963 if (pOp!=NULL) 00964 { 00965 ChangeBrushOpParam BrushParam; 00966 BrushParam.ChangeType = CHANGEBRUSH_REGEN; 00967 ChangeBrushAction* pNewAction; 00968 if (allowed) allowed=(ChangeBrushAction::Init(pOp, pOp->GetUndoActionList(), this, 00969 &BrushParam, &pNewAction) != AC_FAIL); 00970 if (allowed) allowed=pOp->DoInvalidateNodeRegion(this,TRUE); 00971 } 00972 #endif 00973 } 00974 } 00975 else 00976 SetOpPermission(PERMISSION_DENIED,TRUE); 00977 } 00978 00979 // if the op was allowed, inform our children by calling their AllowOp()s 00980 // this must be done after we've inserted our undo actions so that any child undo actions will be undone first! 00981 if (allowed && pParam->GetDirection()!=OBJCHANGE_CALLEDBYCHILD) 00982 AllowOp_AccountForCompound(pParam, SetOpPermissionState); 00983 00984 00985 // return result (directly, or indirectly via a child AllowOp()) to op 00986 return allowed; 00987 } 00988 00989 00990 /******************************************************************************************** 00991 00992 > virtual ChangeCode NodeBlend::OnChildChange(ObjChangeParam* pParam) 00993 00994 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00995 Created: 6/12/99 00996 Inputs: pParam = pointer to a object change parameter class 00997 Returns: CC_OK if we have successfully processed the change. 00998 CC_FAIL if we cannot handle this particular change and must prevent the 00999 child from continuing 01000 Purpose: This function should be overridden in derived object classes. 01001 Composite objects can use this function to respond to one of their children 01002 undergoing a change. They should return CC_FAIL whenever they are unable to 01003 cope with the change. 01004 01005 Brushes simply regenerate themselves at the moment. 01006 01007 SeeAlso: WarnParentOfChange(),AllowOp(); 01008 01009 ********************************************************************************************/ 01010 01011 ChangeCode NodeBrush::OnChildChange(ObjChangeParam* pParam) 01012 { 01013 PORTNOTE("other","NodeBrush::OnChildChange - ChangeBrushAction ChangeBrushOpParam") 01014 #ifndef EXCLUDE_FROM_XARALX 01015 ERROR2IF(pParam == NULL,CC_FAIL,"pParam == NULL"); 01016 01017 ObjChangeType cType = pParam->GetChangeType(); 01018 ObjChangeFlags Flags = pParam->GetChangeFlags(); 01019 01020 if (cType == OBJCHANGE_FINISHED) 01021 { 01022 UndoableOperation* pUndoOp = pParam->GetOpPointer(); 01023 01024 if (pUndoOp == NULL) 01025 { 01026 ERROR3("Couldn't get undo op"); 01027 return CC_FAIL; 01028 } 01029 01030 ChangeBrushAction* pAction; 01031 ChangeBrushOpParam OpParam; 01032 OpParam.ChangeType = CHANGEBRUSH_REGEN; 01033 01034 BOOL ok = (ChangeBrushAction::Init(pUndoOp, pUndoOp->GetUndoActionList(), 01035 this, &OpParam, &pAction) != AC_FAIL); 01036 01037 if (ok) ok = pUndoOp->DoInvalidateNodeRegion(this,TRUE); 01038 01039 if (ok) 01040 return CC_OK; 01041 else 01042 return CC_FAIL; 01043 } 01044 #endif 01045 return CC_OK; 01046 }