00001 // $Id: ndbrshmk.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 class NodeBrushMaker 00100 #include "camtypes.h" 00101 #include "ndbrshmk.h" 00102 #include "attrmap.h" 00103 //#include "progress.h" 00104 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 #include "ndbrshpt.h" 00106 #include "nodebrsh.h" 00107 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 #include "qualattr.h" 00109 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 #include "grndbmp.h" 00111 //#include "camvw.h" 00112 //#include "scrcamvw.h" 00113 #include "grndrgn.h" 00114 //#include "grndbrsh.h" 00115 //#include "quality.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00116 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00117 //#include "quality.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00118 #include "qualattr.h" 00119 00120 class QualityAttribute; 00121 00122 CC_IMPLEMENT_DYNCREATE(NodeBrushMaker, NodeRenderableInk) 00123 00124 00125 #define DELPTR(p) if (p != NULL) { delete p; p = NULL; } 00126 00127 00128 /*********************************************************************************************** 00129 00130 > NodeBrushMarker::NodeBrushMaker(Node* ContextNode, 00131 AttachNodeDirection Direction, 00132 const DocRect& BoundingRect, 00133 BOOL Locked = FALSE, 00134 BOOL Mangled = FALSE, 00135 BOOL Marked = FALSE, 00136 BOOL Selected = FALSE, 00137 BOOL Renderable = FALSE 00138 ) 00139 00140 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00141 Created: 6/10/99 00142 00143 Inputs: ContextNode: Pointer to a node which this node is to be attached to. 00144 MonoOn Direction: MonoOff 00145 Specifies the direction in which the node is to be attached to the 00146 ContextNode. The values this variable can take are as follows: 00147 00148 PREV : Attach node as a previous sibling of the context node 00149 NEXT : Attach node as a next sibling of the context node 00150 FIRSTCHILD: Attach node as the first child of the context node 00151 LASTCHILD : Attach node as a last child of the context node 00152 00153 BoundingRect: Bounding rectangle 00154 00155 The remaining inputs specify the status of the node: 00156 00157 Locked: Is node locked ? 00158 Mangled: Is node mangled ? 00159 Marked: Is node marked ? 00160 Selected: Is node selected ? 00161 00162 Purpose: This constructor initialises the nodes flags and links it to ContextNode in the 00163 direction specified by Direction. All neccesary tree links are updated. 00164 00165 Note: Initialise() must be called before the NodeBrushMaker is in a state in which it can be used. 00166 SeeAlso: Initialise() 00167 Errors: An assertion error will occur if ContextNode is NULL 00168 00169 ***********************************************************************************************/ 00170 00171 NodeBrushMaker::NodeBrushMaker(Node* ContextNode, 00172 AttachNodeDirection Direction, 00173 BOOL Locked, 00174 BOOL Mangled, 00175 BOOL Marked, 00176 BOOL Selected 00177 ):NodeRenderableInk(ContextNode, Direction, Locked, Mangled, Marked, Selected ) 00178 { 00179 ResetMembers(); 00180 } 00181 00182 /********************************************************************************************* 00183 00184 > NodeBrushMaker::NodeBrushMaker() 00185 00186 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00187 Created: 6/10/99 00188 Purpose: This constructor creates a NodeBrushMaker linked to no other with all status 00189 flags false and an uninitialized bounding rectangle. 00190 Note: Initialise() must be called before the NodeBrushMaker is in a state in which it can be 00191 used. 00192 SeeAlso: Initialise() 00193 00194 **********************************************************************************************/ 00195 /* Technical Notes: 00196 The default constructor is required so that SimpleCopy will work 00197 */ 00198 00199 NodeBrushMaker::NodeBrushMaker(): NodeRenderableInk() 00200 { 00201 ResetMembers(); 00202 00203 } 00204 00205 /********************************************************************************************* 00206 00207 > NodeBrushMaker::~NodeBrushMaker() 00208 00209 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00210 Created: 6/10/99 00211 Purpose: Default deconstructor 00212 00213 **********************************************************************************************/ 00214 00215 NodeBrushMaker::~NodeBrushMaker() 00216 { 00217 //delete m_pAttrMap; 00218 PORTNOTETRACE("other","NodeBrushMaker::~NodeBrushMaker - not deleting m_pGRender"); 00219 #ifndef EXCLUDE_FROM_XARALX 00220 DELPTR(m_pGRender); 00221 #endif 00222 if (m_pBlendRef != NULL) 00223 DELPTR(m_pBlendRef); 00224 00225 00226 } 00227 00228 00229 /*********************************************************************************************** 00230 00231 > void NodeBrushMaker::ResetMembers() 00232 00233 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00234 Created: 6/10/99 00235 Inputs: - 00236 Returns - 00237 Purpose: Initialises the member variables 00238 00239 ***********************************************************************************************/ 00240 00241 void NodeBrushMaker::ResetMembers() 00242 { 00243 m_BrushSpacing = 0; 00244 m_BrushStep = 0; 00245 m_MaxStep = 0; 00246 m_CurrentDistance = 0; 00247 00248 m_PositionRandomness = 0.0; 00249 m_AttrRandomness = 0.0; 00250 m_SizeRandomness = 0.0; 00251 m_AlignmentRandomness = 0.0; 00252 m_bRandomizeShape = FALSE; 00253 m_JustTransformed = FALSE; 00254 00255 m_pBlendRef = NULL; 00256 m_pGRender = NULL; 00257 00258 m_PathOffsetType = OFFSET_NONE; 00259 m_PathOffsetValue = 50000; 00260 00261 m_bFirstRender = FALSE; 00262 00263 m_bRotate = FALSE; 00264 m_bTile = TRUE; 00265 m_bUsePathCache = TRUE; 00266 00267 00268 00269 } 00270 00271 00272 /*********************************************************************************************** 00273 00274 > void NodeBrushMaker::InitialiseArray(UINT32 NumObjects) 00275 00276 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00277 Created: 6/10/99 00278 Inputs: Number of objects to size the array at 00279 Returns: - 00280 Purpose: Clears out the m_BrushRefPtrArray if it is not empty, and sets the size 00281 00282 ***********************************************************************************************/ 00283 00284 void NodeBrushMaker::InitialiseBrushArray(UINT32 NumObjects) 00285 { 00286 UINT32 i = 0; 00287 while (i < m_BrushRefPtrArray.size()) 00288 { 00289 delete m_BrushRefPtrArray[i++]; 00290 } 00291 m_BrushRefPtrArray.clear(); 00292 00293 m_BrushRefPtrArray.resize( NumObjects ); 00294 00295 // fill the array with NULL objects so that we can check later 00296 // to see if our allocations have worked 00297 i = 0; 00298 while (i < m_BrushRefPtrArray.size()) 00299 { 00300 m_BrushRefPtrArray[i++] = NULL; 00301 } 00302 00303 } 00304 00305 /*********************************************************************************************** 00306 00307 > virtual Node* NodeBrushMaker::SimpleCopy() 00308 00309 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00310 Created: 6/10/99 00311 Returns: Pointer to a Node 00312 Purpose: Makes a copy of all the data in the node 00313 00314 ***********************************************************************************************/ 00315 00316 Node* NodeBrushMaker::SimpleCopy() 00317 { 00318 // Make a new NodeBrushMaker and then copy things into it 00319 NodeBrushMaker* pCopyOfNode = new NodeBrushMaker(); 00320 if (pCopyOfNode) 00321 CopyNodeContents(pCopyOfNode); 00322 00323 return pCopyOfNode; 00324 } 00325 00326 00327 /*********************************************************************************************** 00328 00329 > void NodeBrushMaker::CopyNodeContents(NodeBrushMaker* pCopyOfNode) 00330 00331 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00332 Created: 6/10/99 00333 Inputs: pCopyOfNode - The node to copy data to 00334 Purpose: Copies the data in this node to pCopyOfNode by first calling the base class to get it to 00335 copy its stuff, and then copying its own stuff 00336 Scope: protected 00337 SeeAlso: NodeRenderableInk::CopyNodeContents 00338 00339 ***********************************************************************************************/ 00340 00341 void NodeBrushMaker::CopyNodeContents(NodeBrushMaker* pCopyOfNode) 00342 { 00343 NodeRenderableInk::CopyNodeContents(pCopyOfNode); 00344 00345 // Copy contents specific to derived class here 00346 00347 00348 } 00349 00350 00351 00352 /*********************************************************************************************** 00353 > void NodeBrushMaker::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00354 00355 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00356 Created: 18/12/2003 00357 Outputs: - 00358 Purpose: Polymorphically copies the contents of this node to another 00359 Errors: An assertion failure will occur if NodeCopy is NULL 00360 Scope: protected 00361 00362 ***********************************************************************************************/ 00363 00364 void NodeBrushMaker::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00365 { 00366 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 00367 ENSURE(IS_A(pNodeCopy, NodeBrushMaker), "PolyCopyNodeContents given wrong dest node type"); 00368 00369 if (IS_A(pNodeCopy, NodeBrushMaker)) 00370 CopyNodeContents((NodeBrushMaker*)pNodeCopy); 00371 } 00372 00373 00374 00375 00376 /*********************************************************************************************** 00377 00378 > void NodeBrushMaker::ShowDebugTreeDetails() const 00379 00380 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00381 Created: 6/10/99 00382 Purpose: Displays debugging info of the tree 00383 SeeAlso: NodeRenderableInk::ShowDebugTreeDetails 00384 00385 ***********************************************************************************************/ 00386 #ifdef _DEBUG 00387 void NodeBrushMaker::ShowDebugTreeDetails() const 00388 { 00389 // Display a bit of debugging info 00390 // For now, we will just call the base class version 00391 NodeRenderableInk::ShowDebugTreeDetails(); 00392 } 00393 #endif 00394 00395 00396 /******************************************************************************************** 00397 00398 > void NodeBrushMaker::GetDebugDetails( StringBase* Str ) 00399 00400 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00401 Created: 6/10/99 00402 Outputs: Str: String giving debug info about the node 00403 Purpose: For obtaining debug information about the Node 00404 00405 ********************************************************************************************/ 00406 00407 void NodeBrushMaker::GetDebugDetails( StringBase* Str ) 00408 { 00409 #ifdef _DEBUG 00410 // Call base class 00411 NodeRenderableInk::GetDebugDetails( Str ); 00412 00413 /* 00414 (*Str) += TEXT( "\r\nBrushMaker Data Dump\r\n" ); 00415 00416 char buf[500]; 00417 sprintf(buf, 00418 ); 00419 00420 *Str += buf; 00421 00422 *Str += "--------- Start\r\n\r\n"; 00423 GetDebugDetails(Str,m_pBlendRef); 00424 00425 */ 00426 #endif 00427 } 00428 00429 00430 /******************************************************************************************** 00431 00432 > void NodeBrushMaker::GetDebugDetails( StringBase* Str,BlendRef* pBlendRef ) 00433 00434 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00435 Created: 22/2/95 00436 Outputs: Str: String giving debug info about the node 00437 Purpose: For obtaining debug information about the blend reference 00438 00439 ********************************************************************************************/ 00440 00441 void NodeBrushMaker::GetDebugDetails( StringBase* Str, BlendRef* pBlendRef ) 00442 { 00443 #ifdef _DEBUG 00444 String_256 TempStr; 00445 00446 TempStr._MakeMsg( _T("Num blend paths = #1%d\r\n"), pBlendRef->GetNumBlendPaths() ); 00447 *Str += TempStr; 00448 BlendPath* pBlendPath = pBlendRef->GetFirstBlendPath(); 00449 while (pBlendPath != NULL) 00450 { 00451 Path* pPath = pBlendPath->GetPath(); 00452 PathVerb* pVerbs = pPath->GetVerbArray(); 00453 PathFlags* pFlags = pPath->GetFlagArray(); 00454 DocCoord* pCoords = pPath->GetCoordArray(); 00455 00456 TempStr._MakeMsg( _T("Original Mapping = #1%d\r\n"), pBlendPath->GetOrigMapping() ); 00457 *Str += TempStr; 00458 00459 for (INT32 i=0; i<pPath->GetNumCoords(); i++) 00460 { 00461 // Add the info to the string 00462 TempStr._MakeMsg( TEXT("#1%d.\t#2%d\t#3%ld,\t#4%ld\t"), 00463 i, pVerbs[i], pCoords[i].x, pCoords[i].y ); 00464 (*Str) += TempStr; 00465 00466 if (pFlags[i].IsEndPoint) 00467 { 00468 TempStr._MakeMsg( _T(": E\t") ); 00469 (*Str) += TempStr; 00470 } 00471 00472 *Str += _T("\r\n"); 00473 } 00474 pBlendPath = pBlendRef->GetNextBlendPath(pBlendPath); 00475 } 00476 #endif 00477 } 00478 00479 00480 00481 /******************************************************************************************** 00482 00483 > virtual void NodeBrushMaker::Transform( TransformBase& Trans ) 00484 00485 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00486 Created: 6/10/99 00487 Inputs: Trans - The transform Object 00488 Purpose: Transforms all the paths attached to this blender node 00489 SeeAlso: NodeRenderableInk::Transform() 00490 00491 ********************************************************************************************/ 00492 00493 void NodeBrushMaker::Transform( TransformBase& Trans ) 00494 { 00495 InvalidateBoundingRect(); 00496 // transform the blendref object 00497 m_pBlendRef->Transform(Trans); 00498 00499 // clear out the list of points to render 00500 m_ListOfPointsToRender.clear(); 00501 00502 // set the awful hacky flag 00503 m_JustTransformed = TRUE; 00504 } 00505 00506 00507 00508 /*********************************************************************************************** 00509 00510 > void NodeBrushMaker::Render(RenderRegion* pRender) 00511 00512 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00513 Created: 6/10/99 00514 Inputs: Pointer to a render region 00515 Purpose: Will render the blendpath objects on to the path of the brush 00516 00517 ***********************************************************************************************/ 00518 00519 void NodeBrushMaker::Render(RenderRegion* pRender) 00520 { 00521 PORTNOTETRACE("other","NodeBrushMaker::Render - do nothing"); 00522 #ifndef EXCLUDE_FROM_XARALX 00523 // first check to see what we need to render 00524 DocRect RenderRect = pRender->GetClipRect(); 00525 00526 DocRect BrushRect = this->GetBoundingRect(); 00527 00528 DocRect TestRect = RenderRect.Intersection(BrushRect); 00529 00530 // if there is no intersection we can just quit now 00531 00532 if (!TestRect.IsIntersectedWith(RenderRect)) 00533 { 00534 //TRACEUSER( "Diccon", _T("Brush not in render rect")); 00535 return; 00536 } 00537 // TRACEUSER( "Diccon", _T("\nBrushRect Top = %d, %d, Bot = %d, %d\n"), BrushRect.hix, BrushRect.hiy, BrushRect.lox, BrushRect.loy); 00538 00539 // TRACEUSER( "Diccon", _T("\nRenderRect Top = %d, %d, Bot = %d, %d\n"), RenderRect.hix, RenderRect.hiy, RenderRect.lox, RenderRect.loy); 00540 00541 // if we still have some points to render from last time then 00542 // go ahead and do those. if not then test to see if the 00543 // render region contains the brush, in which case we need all the 00544 // points, or if we just need to find out which points belong in the list 00545 00546 if (m_ListOfPointsToRender.IsEmpty()) 00547 { 00548 //TRACEUSER( "Diccon", _T("Empty\n")); 00549 m_BrushStep = 0; 00550 if (RenderRect.ContainsRect(BrushRect)) 00551 AddAllPointsToList(); 00552 else 00553 AddPointsInRectToList(RenderRect); 00554 } 00555 00556 // we only want to use the caching system once, so if we have just used it then 00557 // turn it off and tell the NBP we have stopped 00558 if (m_bUsePathCache == TRUE) 00559 { 00560 m_bUsePathCache = FALSE; 00561 m_pNodeBrushPath->StoppedBrush(); 00562 } 00563 // we now have a list of points to render 00564 //TRACEUSER( "Diccon", _T("\nNum points = %d\n"), m_ListOfPointsToRender.GetCount()); 00565 00566 00567 // set the quality level 00568 if (pRender->RRQuality.GetAntialiasQuality() != Quality::FullAntialias) 00569 { 00570 // Create a non-antialias quality attr to render 00571 Quality Qual; 00572 Qual.SetQuality(QUALITY_MAX); 00573 QualityAttribute *pQualAttrVal = new QualityAttribute(Qual); 00574 if (pQualAttrVal != NULL) 00575 { 00576 // Render the attribute, and mark it Temporary so it will be auto-deleted 00577 // when it is finished with. 00578 pRender->SetQuality(pQualAttrVal, TRUE); 00579 } 00580 } 00581 00582 BOOL ContinueRender = TRUE; 00583 View* pView = pRender->GetRenderView(); 00584 CPathPointInfo Point; 00585 m_AltValue = 0; 00586 m_bFirstRender = TRUE; 00587 while (ContinueRender && (m_ListOfPointsToRender.IsEmpty() == FALSE)) 00588 { 00589 Point = m_ListOfPointsToRender.GetHead(); 00590 m_ListOfPointsToRender.RemoveHead(); 00591 RenderBrushObjectAtPoint(Point, pRender); 00592 00593 // okay, so there was a problem in that when the node was transformed 00594 // it would not completely re-render itself because it kept timing out. 00595 // this is a hacky fix so that for the first render after the transformation 00596 // we force it to do the whole thing. 00597 // if (!m_JustTransformed) 00598 // ContinueRender = pView->CanContinue(pRender); 00599 00600 // if (!ContinueRender) 00601 // TRACEUSER( "Diccon", _T("TIMED OUT\n"); //"Continue = %d\n"), ContinueRender); 00602 if (m_AltValue == 0) 00603 m_AltValue = 1; 00604 else 00605 m_AltValue = 0; 00606 //m_bFirstRender = FALSE; 00607 } 00608 00609 if (m_JustTransformed == TRUE) 00610 m_JustTransformed = FALSE; 00611 00612 //TRACEUSER( "Diccon", _T("Finished render with %d objects in list\n"), m_ListOfPointsToRender.GetCount()); 00613 00614 if (m_ListOfPointsToRender.GetCount() == 0) 00615 { 00616 00617 00618 } 00619 else 00620 { 00621 00622 } 00623 00624 pRender->LockSubRenderState(FALSE); 00625 #endif 00626 } 00627 00628 00629 00630 00631 00632 /******************************************************************************************** 00633 00634 > void NodeBrushMaker::RenderAttributes(RenderRegion* pRender, CCAttrMap* pAttrMap) 00635 00636 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00637 Created: 6/10/99 00638 Inputs: pRender = ptr to render region 00639 pAttrMap - the attribute map to render 00640 Outputs: - 00641 Returns: - 00642 Purpose: Renders the attributes to the given render region 00643 SeeAlso: - 00644 00645 ********************************************************************************************/ 00646 00647 void NodeBrushMaker::RenderAttributes(RenderRegion* pRender, CCAttrMap* pAttrMap) 00648 { 00649 PORTNOTETRACE("other","NodeBrushMaker::RenderAttributes - do nothing"); 00650 #ifndef EXCLUDE_FROM_XARALX 00651 // Check entry params 00652 BOOL ok = (pRender != NULL && pAttrMap != NULL); 00653 ERROR3IF(!ok,"One or more NULL entry params"); 00654 if (!ok) return; 00655 00656 void* pType; 00657 void* pVal; 00658 NodeAttribute* pNodeAttr; 00659 // iterating all (key, value) pairs 00660 for (POSITION Pos = pAttrMap->GetStartPosition(); Pos != NULL;) 00661 { 00662 // Get attr at position Pos 00663 pAttrMap->GetNextAssoc(Pos,pType,pVal); 00664 00665 // pVal is actually an attribute, so get a ptr to it and render it 00666 pNodeAttr = (NodeAttribute *)pVal; 00667 00668 // we only need to render most of the attributes once 00669 if (m_bFirstRender == FALSE) 00670 { 00671 if (pNodeAttr->NeedsToRenderAtEachBrushStroke()) 00672 pNodeAttr->Render(pRender); 00673 } 00674 else 00675 pNodeAttr->Render(pRender); 00676 00677 } 00678 #endif 00679 } 00680 00681 00682 00683 00684 /*********************************************************************************************** 00685 00686 > void NodeBrushMaker::RenderStep(INT32 StepNum, Spread* pSpread, DocCoord Point) 00687 00688 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00689 Created: 6/10/99 00690 Inputs: StepNum - the step number to render 00691 pSpread - the current spread 00692 Point - the coordinate to render the step 00693 Purpose: To draw the brush stroke to the screen as quickly as possible. This is 00694 achieved by drawing the path and attributes to the render region, the blitting 00695 straight away. 00696 00697 ***********************************************************************************************/ 00698 00699 void NodeBrushMaker::RenderStep(INT32 StepNum, Spread* pSpread, CPathPointInfo Point) 00700 { 00701 PORTNOTETRACE("other","NodeBrushMaker::RenderStep - do nothing"); 00702 #ifndef EXCLUDE_FROM_XARALX 00703 //TRACEUSER( "Diccon", _T("Rendering Step %d\n"), StepNum); 00704 if (StepNum == 0) 00705 m_bFirstRender = TRUE; 00706 00707 if (StepNum == 1) 00708 m_bFirstRender = FALSE; 00709 00710 00711 DocView* pView = DocView::GetSelected(); 00712 DocRect ViewRect =m_pGRenderDIB->GetClipRect(); 00713 00714 if (Point.m_Point.x > ViewRect.hix || Point.m_Point.x < ViewRect.lox) 00715 INT32 i = 1; 00716 if (Point.m_Point.y > ViewRect.hiy || Point.m_Point.y < ViewRect.loy) 00717 INT32 j = 1; 00718 00719 if (pView == NULL) 00720 { 00721 ERROR3("No View!"); 00722 return; 00723 } 00724 00725 00726 // declare variables to be used in loop 00727 DocRect BRect; 00728 DocRect ChangedRect; 00729 DocCoord CurrentPoint; 00730 Trans2DMatrix Trans; 00731 Trans2DMatrix Rotate; 00732 00733 // get the head position of the offset list 00734 POSITION ListPosition; // = m_OffsetList.GetHeadPosition(); 00735 BlendPathOffset ListOffset; //m_OffsetList.GetNext(ListPosition); 00736 BlendPath* pBlendPath = m_pBlendRef->GetFirstBlendPath(); 00737 00738 CCAttrMap* pAttrMap = NULL; 00739 00740 00741 // pass alternating values into SetPosition so that it can do 00742 // alternating offsets 00743 UINT32 AltValue; 00744 if (StepNum % 2 == 0) 00745 AltValue = 0; 00746 else 00747 AltValue = 1; 00748 00749 00750 DocCoord CopyPoint; 00751 // the rendering loop 00752 //m_pGRenderDIB->StartRender(); 00753 while (pBlendPath != NULL) 00754 { 00755 // get the correct transformation 00756 CopyPoint = SetPosition(Point,AltValue, &ListPosition); 00757 00758 if (ListPosition != NULL) 00759 ListOffset = m_OffsetList.GetNext(ListPosition); 00760 00761 BRect = pBlendPath->m_pPath->GetBoundingRect(); 00762 CurrentPoint = BRect.Centre(); 00763 BRect.Translate((CopyPoint.x - CurrentPoint.x), (CopyPoint.y - CurrentPoint.y)); 00764 Trans.SetTransform((CopyPoint.x - CurrentPoint.x), (CopyPoint.y - CurrentPoint.y)); 00765 if (m_bRotate) 00766 { 00767 Rotate.SetTransform(CopyPoint, Point.m_Tangent); 00768 Trans.operator *=(Rotate); 00769 } 00770 00771 // transform the points in the path 00772 Trans.Transform( (DocCoord*)pBlendPath->m_pPath->GetCoordArray(), pBlendPath->m_pPath->GetNumCoords()); 00773 00774 // get the attribute map 00775 pAttrMap = pBlendPath->FindAppliedAttributes(); 00776 if (pAttrMap == NULL) 00777 ERROR3("No applied attributes"); 00778 00779 // transform the attribute map either to tile or not 00780 if (!m_bTile) 00781 pAttrMap->Transform(Trans); 00782 else 00783 pAttrMap->TransformForBrush(Trans); 00784 00785 RenderAttributes(m_pGRenderDIB, pAttrMap); 00786 m_pGRenderDIB->DrawPath(pBlendPath->m_pPath); 00787 00788 00790 pBlendPath = m_pBlendRef->GetNextBlendPath(pBlendPath); 00791 00792 ChangedRect = ChangedRect.Union(BRect); 00793 00794 } 00795 //m_pGRenderDIB->StopRender(); 00796 // set the changed bounding box for the render region so that when we come 00797 // to blit we only blit the pixels that have changed 00798 m_pGRenderDIB->SetChangedBBox(ChangedRect); 00799 // m_pGRenderDIB->PlotBrushIntoBigBitmap(ChangedRect); 00800 m_pGRenderDIB->DrawToScreenNow(); 00801 00802 00803 // //TRACEUSER( "Diccon", _T("Left render loop")); 00804 #endif 00805 } 00806 00807 /******************************************************************************************** 00808 00809 > void NodeBrushMaker::RenderEorDrag( RenderRegion* pRender ) 00810 00811 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00812 Created: 6/10/99 00813 Inputs: pRender - A Pointer to the current RenderRegion 00814 Purpose: Renders a version of the blender node for EORed dragging of blends. 00815 SeeAlso: NodePath::Render; NodeRenderableInk::RenderEorDrag 00816 00817 ********************************************************************************************/ 00818 00819 void NodeBrushMaker::RenderEorDrag( RenderRegion* pRender ) 00820 { 00821 00822 } 00823 00824 00825 00826 /******************************************************************************************** 00827 00828 > DocRect NodeBrushMaker::GetBoundingRect(BOOL DontUseAttrs=FALSE, BOOL HitTest=FALSE) 00829 00830 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00831 Created: 6/10/99 00832 Inputs: DontUseAttrs - TRUE if we should ignore the nodes attributes. 00833 Defaults to FALSE 00834 HitTest - TRUE if being called during HitTest 00835 Returns: The nodes bounding rect 00836 Purpose: if the bounding rect is valid it is returned, if not, it is recalculated 00837 and then returned. 00838 SeeAlso: NodeBrushMaker::GetBlobBoundingRect 00839 00840 ********************************************************************************************/ 00841 00842 DocRect NodeBrushMaker::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest) 00843 { 00844 DocRect Rect; 00845 // double Distance = m_pNodeBrushPath->GetPathLength(); 00846 // //TRACEUSER( "Diccon", _T("Path length %d\n"), Distance); 00847 // m_pNodeBrushPath->InvalidateBoundingRect(); 00848 Rect = m_pNodeBrushPath->GetBoundingRect(); 00849 Rect.Inflate(m_BrushBoundingRect.Width()/2, m_BrushBoundingRect.Height()/2); 00850 if (m_PathOffsetType != OFFSET_NONE) 00851 Rect.Inflate(m_PathOffsetValue, m_PathOffsetValue); 00852 return Rect; 00853 00854 } 00855 00856 00857 /******************************************************************************************** 00858 00859 > DocRect NodeBrushMaker::GetBlobBoundingRect() 00860 00861 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00862 Created: 6/10/99 00863 Returns: DocRect - Returns the bounding rect of the brushmaker node and its blobs 00864 Purpose: 00865 00866 ********************************************************************************************/ 00867 00868 DocRect NodeBrushMaker::GetBlobBoundingRect() 00869 { 00870 return (GetBoundingRect()); 00871 } 00872 00873 00874 00875 00876 /******************************************************************************************** 00877 00878 > virtual UINT32 NodeBrushMaker::GetNodeSize() const 00879 00880 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00881 Created: 6/10/99 00882 Returns: The size of the node in bytes 00883 Purpose: For finding the size of the node 00884 SeeAlso: Node::GetSubtreeSize 00885 00886 ********************************************************************************************/ 00887 00888 UINT32 NodeBrushMaker::GetNodeSize() const 00889 { 00890 return (sizeof(NodeBrushMaker)); 00891 } 00892 00893 00894 00895 00896 /******************************************************************************************** 00897 00898 > BOOL NodeBrushMaker::SetBrushSpacing(double Spacing) 00899 00900 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00901 Created: 6/10/99 00902 Inputs: the spacing value to set 00903 Returns: TRUE if successful, FALSE if the spacing is invalid 00904 Purpose: To set the spacing between brush objects 00905 SeeAlso: - 00906 00907 ********************************************************************************************/ 00908 00909 BOOL NodeBrushMaker::SetBrushSpacing(MILLIPOINT Spacing) 00910 { 00911 // if (Spacing < MIN_BRUSH_SPACING || Spacing > MAX_BRUSH_SPACING) 00912 // return FALSE; 00913 00914 m_BrushSpacing = Spacing; 00915 00916 return TRUE; 00917 00918 } 00919 00920 00921 00922 /******************************************************************************************** 00923 00924 > MILLIPOINT NodeBrushMaker::GetBrushSpacing() 00925 00926 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00927 Created: 6/10/99 00928 Returns: the spacing between the brush objects 00929 Purpose: As above 00930 00931 ********************************************************************************************/ 00932 00933 MILLIPOINT NodeBrushMaker::GetBrushSpacing() 00934 { 00935 return m_BrushSpacing; 00936 } 00937 00938 00939 00940 00941 /******************************************************************************************** 00942 00943 > PathOffset NodeBrushMaker::GetPathOffsetType() 00944 00945 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00946 Created: 6/10/99 00947 Inputs: - 00948 Returns: The type of pathoffset this brush is using 00949 Purpose: as above 00950 SeeAlso: - 00951 00952 ********************************************************************************************/ 00953 00954 PathOffset NodeBrushMaker::GetPathOffsetType() 00955 { 00956 return m_PathOffsetType; 00957 } 00958 00959 00960 00961 /******************************************************************************************** 00962 00963 > void NodeBrushMaker::SetPathOffsetType(PathOffset Offset) 00964 00965 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00966 Created: 6/10/99 00967 Inputs Offset - the offset type to set 00968 Returns: - 00969 Purpose: to set the offset type for this brush 00970 ********************************************************************************************/ 00971 void NodeBrushMaker::SetPathOffsetType(PathOffset Offset) 00972 { 00973 m_PathOffsetType = Offset; 00974 } 00975 00976 00977 /******************************************************************************************** 00978 00979 > MILLIPOINT NodeBrushMaker::GetPathOffsetValue() 00980 00981 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00982 Created: 6/10/99 00983 Inputs: - 00984 Returns: The value of the path offset used by this brush 00985 Purpose: as above 00986 SeeAlso: - 00987 00988 ********************************************************************************************/ 00989 00990 MILLIPOINT NodeBrushMaker::GetPathOffsetValue() 00991 { 00992 return m_PathOffsetValue; 00993 } 00994 00995 00996 00997 /******************************************************************************************** 00998 00999 > void NodeBrushMaker::SetPathOffsetValue(MILLIPOINT Value) 01000 01001 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01002 Created: 6/10/99 01003 Inputs Value - the offset value to set 01004 Returns: - 01005 Purpose: to set the offset distance for this brush 01006 ********************************************************************************************/ 01007 void NodeBrushMaker::SetPathOffsetValue(MILLIPOINT Value) 01008 { 01009 m_PathOffsetValue = Value; 01010 } 01011 01012 01013 01014 /******************************************************************************************** 01015 01016 > void NodeBrushMaker::SetNumberOfSteps(INT32 Steps) 01017 01018 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01019 Created: 6/10/99 01020 Inputs: the number of steps to set 01021 Returns: - 01022 Purpose: To set the number of steps 01023 SeeAlso: - 01024 01025 ********************************************************************************************/ 01026 01027 void NodeBrushMaker::SetNumberOfSteps(INT32 Steps) 01028 { 01029 m_MaxStep = Steps; 01030 01031 } 01032 01033 01034 /******************************************************************************************** 01035 01036 > void NodeBrushMaker::SetRotated(BOOL Rotate) 01037 01038 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01039 Created: 6/10/99 01040 Inputs: Rotate - boolean value to set 01041 Returns: - 01042 Purpose: To set the rotate member 01043 SeeAlso: - 01044 01045 ********************************************************************************************/ 01046 01047 void NodeBrushMaker::SetRotated(BOOL Rotate) 01048 { 01049 m_bRotate = Rotate; 01050 } 01051 01052 01053 /******************************************************************************************** 01054 01055 > BOOL NodeBrushMaker::GetRotated() 01056 01057 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01058 Created: 6/10/99 01059 Inputs: - 01060 Returns: Current value of m_bRotate 01061 Purpose: as above 01062 SeeAlso: - 01063 01064 ********************************************************************************************/ 01065 01066 BOOL NodeBrushMaker::GetRotated() 01067 { 01068 return m_bRotate; 01069 } 01070 01071 01072 01073 /******************************************************************************************** 01074 01075 > void NodeBrushMaker::SetUsePathCache(BOOL Value) 01076 01077 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01078 Created: 6/10/99 01079 Inputs: the value to set 01080 Returns: - 01081 Purpose: To tell the nbm to ask the nbp to use its cached path processor to get 01082 points along the path. This will speed up the first render after an alteration 01083 in the path. However after the first rendering pass it should be set to false 01084 again because a) the points themselves will be cached and b)the cached processor 01085 will probably be deleted. 01086 SeeAlso: - 01087 01088 ********************************************************************************************/ 01089 01090 void NodeBrushMaker::SetUsePathCache(BOOL Value) 01091 { 01092 m_bUsePathCache = Value; 01093 01094 } 01095 01096 /******************************************************************************************** 01097 01098 > BOOL NodeBrushMaker::InitialiseInk(NodeRenderableInk* pInk, BlendRef* pBlendRef,Progress* pProgress ) 01099 01100 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01101 Created: 6/10/99 01102 Inputs: pInk - array of Ink nodes to make the brush objects from 01103 pBlendRef - blendref to make the brush from, default is NULL 01104 pProgress - defaults to NULL 01105 Outputs: - 01106 Returns: TRUE if successful, otherwise FALSE 01107 Purpose: To initialise the blendref, which creates the blendpaths that 01108 are placed along the NodeBrushPath to render the brush. 01109 01110 01111 ********************************************************************************************/ 01112 01113 BOOL NodeBrushMaker::InitialiseInk(NodeRenderableInk** ppInkNode, const UINT32 NumInkNodes, Progress* pProgress) 01114 { 01115 ERROR2IF(*ppInkNode == NULL,FALSE,"pThisNode == NULL"); 01116 ERROR2IF(NumInkNodes == 0, FALSE, "No ink nodes"); 01117 01118 InitialiseBrushArray(NumInkNodes); 01119 01120 UINT32 i = 0; 01121 while (i < NumInkNodes) 01122 { 01123 m_BrushRefPtrArray[i] = new BrushRef; 01124 ERROR2IF(m_BrushRefPtrArray[i] == NULL, FALSE, "Unable to allocate brushref object"); 01125 if (!m_BrushRefPtrArray[i]->Initialise(ppInkNode[i])) 01126 { 01127 ERROR3("Failed to initialise brushref"); 01128 InitialiseBrushArray(MAX_BRUSH_OBJECTS); 01129 return FALSE; 01130 } 01131 i++; 01132 } 01133 01134 return TRUE; 01135 } 01136 01137 #if 0 // not clear when all this was removed AB20060106 01138 m_pInkNode = *pInkNode; 01139 01140 if (m_pBlendRef != NULL) 01141 { 01142 delete m_pBlendRef; 01143 m_pBlendRef = NULL; 01144 } 01145 01146 BOOL ok = TRUE; 01147 for (UINT32 i = 0; i < NumInkNodes; i++) 01148 { 01149 01150 // allocate a new blendref 01151 m_pBlendRef = new BlendRef; 01152 if (ok) ok = (m_pBlendRef != NULL); 01153 if (ok) ok = m_pBlendRef->Initialise(*pInkNode, -1, NULL, pProgress, FALSE, NULL); 01154 01155 DocRect BRect = m_pBlendRef->GetBoundingRect(); 01156 DocCoord InkCentre = BRect.Centre(); 01157 01158 m_OffsetList.RemoveAll(); 01159 01160 if (ok) 01161 { 01162 // get the first blendpath as we need to pass it to the function 01163 // that retrieves the attributes 01164 BlendPath* pBlendPath = m_pBlendRef->GetFirstBlendPath(); 01165 m_BrushBoundingRect = pBlendPath->m_pPath->GetBoundingRect(); 01166 while (pBlendPath != NULL) 01167 { 01168 // copy the attributes of the blendref into our map 01169 /* if (ok) 01170 { 01171 m_pAttrMap = m_pBlendRef->FindAppliedAttributes(pBlendPath); 01172 ok = (m_pAttrMap != NULL); 01173 } 01174 01175 // find out how far each blendpath is offset from the centre of 01176 // the bounding box and record it. 01177 DocRect BlendPathRect = pBlendPath->m_pPath->GetBoundingRect(); 01178 m_BrushBoundingRect = m_BrushBoundingRect.Union(BlendPathRect); 01179 01180 DocCoord BlendPathCentre = BlendPathRect.Centre(); 01181 BlendPathOffset ThisOffset; 01182 ThisOffset.m_XOffset = BlendPathCentre.x - InkCentre.x ; 01183 ThisOffset.m_YOffset = BlendPathCentre.y - InkCentre.y; 01184 // TRACEUSER( "Diccon", _T("Offset = %d, %d\n"), ThisOffset.m_XOffset, ThisOffset.m_YOffset); 01185 // m_OffsetList.AddTail(ThisOffset); 01186 pBlendPath = m_pBlendRef->GetNextBlendPath(pBlendPath); 01187 } 01188 } 01189 } 01190 01191 POSITION ListPosition = m_OffsetList.GetHeadPosition(); 01192 while (ListPosition != NULL) 01193 { 01194 BlendPathOffset Offset = m_OffsetList.GetNext(ListPosition); 01195 //TRACEUSER( "Diccon", _T("List offset %d, %d\n"), Offset.m_XOffset, Offset.m_YOffset); 01196 } 01197 01198 01199 return ok; 01200 01201 } 01202 */ 01203 #endif 01204 01205 /******************************************************************************************** 01206 01207 > void NodeBrushMaker::InitialisePath(NodeBrushPath* pBrushPath) 01208 01209 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01210 Created: 6/10/99 01211 Inputs: NodeBrushPath 01212 Outputs: - 01213 Returns: TRUE if successful, otherwise FALSE 01214 Purpose: To set the NodeBrushPath that the Brushmaker will use to render the brush 01215 objects to 01216 01217 ********************************************************************************************/ 01218 01219 BOOL NodeBrushMaker::InitialisePath(NodeBrushPath* pNodeBrushPath) 01220 { 01221 if (pNodeBrushPath == NULL) 01222 return FALSE; 01223 m_pNodeBrushPath = pNodeBrushPath; 01224 return TRUE; 01225 } 01226 01227 01228 /******************************************************************************************** 01229 01230 > NodeRenderableInk* NodeBrushMaker::GetInkNode() 01231 01232 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01233 Created: 6/10/99 01234 Inputs: - 01235 Outputs: - 01236 Returns: TRUE if successful, FALSE if the start coordinate has not been set 01237 Purpose: To get the inknode used to make the brush 01238 SeeAlso: - 01239 01240 ********************************************************************************************/ 01241 01242 NodeRenderableInk* NodeBrushMaker::GetInkNode() 01243 { 01244 return m_pInkNode; 01245 } 01246 01247 01248 /******************************************************************************************** 01249 01250 > void NodeBrushMaker::RandomizeShape(Trans2DMatrix* pTransformMatrix) 01251 01252 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01253 Created: 6/10/99 01254 Inputs: Matrix containing current transformation 01255 Outputs: matrix with added transformatio caused by randomization 01256 Returns: - 01257 Purpose: To add randomization to the blendpath to be rendered. Transformations 01258 are calculated for the three different types of randomization possible 01259 and combined with the transformation matrix used to translate to the point 01260 along the nodebrushpath 01261 01262 ********************************************************************************************/ 01263 01264 void NodeBrushMaker::RandomizeShape(Trans2DMatrix* pTransMatrix) 01265 { 01266 // err, not sure yet 01267 01268 } 01269 01270 01271 01272 /******************************************************************************************** 01273 01274 > void NodeBrushMaker::RandomizeAttributes() 01275 01276 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01277 Created: 6/10/99 01278 Inputs: - 01279 Outputs: - 01280 Returns: - 01281 Purpose: To add randomization to the attributes of the brush object 01282 01283 ********************************************************************************************/ 01284 01285 void NodeBrushMaker::RandomizeAttributes() 01286 { 01287 01288 } 01289 01290 01291 01292 /******************************************************************************************** 01293 01294 > BOOL NodeBrushMaker::PrepareToRender() 01295 01296 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01297 Created: 21/10/99 01298 Inputs: pSpread - the current spread 01299 Outputs: - 01300 Returns: TRUE if successful, FALSE otherwise 01301 Purpose: Sets up the render region and renders the existing view into it. Call this 01302 before rendering any brush steps/ 01303 01304 ********************************************************************************************/ 01305 01306 BOOL NodeBrushMaker::PrepareToRender(Spread* pSpread) 01307 { 01308 PORTNOTETRACE("other","NodeBrushMaker::PrepareToRender - do nothing"); 01309 #ifndef EXCLUDE_FROM_XARALX 01310 DocView* pView = DocView::GetSelected(); 01311 01312 if (pView == NULL) 01313 { 01314 ERROR3("No View!"); 01315 return FALSE; 01316 } 01317 01318 DocRect ViewRect = pView->GetDocViewRect(pSpread); 01319 01320 if (!GetGRenderBitmap(&ViewRect, &m_pGRender, pSpread)) 01321 { 01322 ERROR3("Failed to get render region"); 01323 return FALSE; 01324 } 01325 01326 if (!DrawViewToRenderRegion(pSpread, m_pGRender)) 01327 { 01328 // //TRACEUSER( "Diccon", _T("Failed to draw view\n")); 01329 return FALSE; 01330 } 01331 01332 01333 m_pGRender->StartRender(); 01334 return TRUE; 01335 #else 01336 return FALSE; 01337 #endif 01338 } 01339 01340 01341 01342 /******************************************************************************************** 01343 01344 > void NodeBrushMaker::FinishRender() 01345 01346 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01347 Created: 21/10/99 01348 Inputs: - 01349 Outputs: - 01350 Returns: - 01351 Purpose: Informs the NBM that the 'creation' phase of rendering has finished. Deletes 01352 the bitmap 01353 01354 ********************************************************************************************/ 01355 01356 void NodeBrushMaker::FinishRender() 01357 { 01358 if (m_pGRenderDIB != NULL) 01359 { 01360 // m_pGRender->StopRender(); 01361 PORTNOTETRACE("other","NodeBrushMaker::FinishRender - not deleting m_pGRenderDIB"); 01362 #ifndef EXCLUDE_FROM_XARALX 01363 delete m_pGRenderDIB; 01364 #endif 01365 m_pGRenderDIB = NULL; 01366 } 01367 m_bFirstRender = FALSE; 01368 01369 if (m_pNodeBrushPath != NULL) 01370 m_pNodeBrushPath->StoppedBrush(); 01371 01372 } 01373 01374 /******************************************************************************************** 01375 01376 > BOOL NodeBrushMaker::GetGRenderBitmap(DocRect* pRect, GRenderBitmap* pGRender) 01377 01378 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01379 Created: 6/10/99 01380 Inputs: pRect - the bounding rectangle of the render region we want to create 01381 Outputs: pGRender - a new GRenderBitmap 01382 Returns: TRUE if successful, FALSE otherwise 01383 Purpose: To return a GRenderDIB, if we don't already have one then create one, if we 01384 do then simply resize it to save time 01385 01386 ********************************************************************************************/ 01387 01388 BOOL NodeBrushMaker::GetGRenderBitmap(DocRect* pRenderRect, GRenderBrush** ppGRender, Spread* pSpread) 01389 { 01390 PORTNOTETRACE("other","NodeBrushMaker::GetGRenderBitmap - do nothing"); 01391 #ifndef EXCLUDE_FROM_XARALX 01392 // if it already points at something then delete it 01393 if (*ppGRender != NULL) 01394 delete *ppGRender; 01395 01396 // now we need to make a new one 01397 01398 // Lets setup a few variables need to create the new BMP 01399 View* pView = View::GetCurrent(); 01400 Matrix Mat(1,0,0,1,0,0); 01401 FIXED16 Scale = 1; 01402 01403 01404 01405 // Check to see if we`ve got an empty rect if so then return NULL! 01406 ERROR2IF(pRenderRect->IsEmpty(),FALSE,"We`ve got an empty DocRect"); 01407 01408 DocRect CopyRect = *pRenderRect; 01409 // Create a new GRenderBitmap region at 32BPP and 96 DPI 01410 GRenderBrush* pNewGRender = new GRenderBrush(CopyRect, Mat, Scale, 32, 96); // FALSE, 0, NULL, TRUE); 01411 01412 // Check to see if the Render Region is valid! 01413 ERROR2IF(pNewGRender == NULL,FALSE,"Failed to create a GRenderBitmap in "); 01414 01415 // Start to render into region! 01416 if(!pNewGRender->AttachDevice(pView, NULL, NULL)) 01417 { 01418 ERROR3("Cannot attatch devices"); 01419 01420 delete pNewGRender; 01421 pNewGRender = NULL; 01422 01423 return FALSE; 01424 } 01425 01426 01427 // pNewGRender->m_DoCompression = TRUE; 01428 01429 pNewGRender->InitAttributes(); 01430 pNewGRender->RRQuality.SetQuality(QUALITY_MAX); 01431 pNewGRender->SetQualityLevel(); 01432 pNewGRender->SetLineAttributes(); 01433 pNewGRender->SetFillAttributes(); 01434 pNewGRender->SetImmediateRender(TRUE); 01435 01436 BOOL ok = pNewGRender->AttachDevice(pView, pView->GetRenderDC(), pSpread); 01437 if (ok) 01438 { 01439 pNewGRender->InitDevice(); 01440 *ppGRender = pNewGRender; 01441 01442 } 01443 return ok; 01444 #endif 01445 return false; 01446 } 01447 /******************************************************************************************** 01448 01449 > BOOL NodeBrushMaker::DrawViewToRenderRegion(Spread* pSpread, RenderRegion* pRender) 01450 01451 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01452 Created: 6/10/99 01453 Inputs: pSpread - pointer to the current spread 01454 pRender - the region to render to 01455 Outputs: - 01456 Returns: TRUE if successful, FALSE otherwise 01457 Purpose: To render whats currently in the tree onto the render region 01458 01459 ********************************************************************************************/ 01460 01461 BOOL NodeBrushMaker::DrawViewToRenderRegion(Spread* pSpread, RenderRegion* pRender) 01462 { 01463 01465 if(pRender != NULL) 01466 { 01467 // get the view 01468 DocView* pDocView = DocView::GetCurrent(); 01469 if (pDocView != FALSE) 01470 { 01471 01472 // draw the view, 01473 pDocView->ContinueRenderView(pRender, pSpread, TRUE, FALSE); 01474 01475 // render the brush so far 01476 01477 Render(pRender); 01478 01479 // //TRACEUSER( "Diccon", _T("\nFinished Drawing View\n")); 01480 return TRUE; 01481 } 01482 else 01483 return FALSE; 01484 } 01485 else 01486 return FALSE; 01487 01488 } 01489 01490 01491 01492 /******************************************************************************************** 01493 01494 > BOOL NodeBrushMaker::GetStartCoord(DocCoord* Coord) 01495 01496 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01497 Created: 6/10/99 01498 Inputs: - 01499 Outputs: the starting coordinate of the brush 01500 Returns: TRUE if successful, FALSE if the start coordinate has not been set 01501 Purpose: To get the starting coordinate of the brush 01502 SeeAlso: - 01503 01504 ********************************************************************************************/ 01505 01506 BOOL NodeBrushMaker::GetStartCoord(DocCoord* pCoord) 01507 { 01508 *pCoord = m_StartCoord; 01509 01510 return TRUE; 01511 } 01512 01513 01514 01515 /******************************************************************************************** 01516 01517 > void NodeBrushMaker::AddPointsInRectToList(DocRect Rect) 01518 01519 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01520 Created: 6/10/99 01521 Inputs: Rect - the rect in which we look for brush objects 01522 Outputs: - 01523 Returns: - 01524 Purpose: To determine which of the brush objects intersect with Rect, these are then 01525 added to the list of points to render 01526 01527 ********************************************************************************************/ 01528 01529 void NodeBrushMaker::AddPointsInRectToList(DocRect Rect) 01530 { 01531 01532 //TRACEUSER( "Diccon", _T("\nAdding points in RECT\n")); 01533 01534 MILLIPOINT DistanceToPoint = 0; 01535 01536 DocCoord TopRight; 01537 DocCoord PointToCheck; 01538 DocCoord BottomLeft; 01539 CPathPointInfo PathPoint; 01540 double Angle; 01541 BOOL ok; 01542 MILLIPOINT Width = m_BrushBoundingRect.Width() / 2; 01543 MILLIPOINT Height = m_BrushBoundingRect.Height() / 2; 01544 while (DistanceToPoint < (m_MaxStep * m_BrushSpacing)) 01545 { 01546 01547 ok = m_pNodeBrushPath->GetPointAtDistance(DistanceToPoint, &PointToCheck, &Angle, m_bUsePathCache ); 01548 if (ok) 01549 { 01550 // we need to compare the bounding rect of a brush object centred at 01551 // PointToCheck. m_BrushBoundingRect holds the correct dimensions of the brush 01552 01553 01554 TopRight.x = PointToCheck.x + Width; 01555 TopRight.y = PointToCheck.y + Height ; 01556 01557 01558 BottomLeft.x = PointToCheck.x - Width; 01559 BottomLeft.y = PointToCheck.y - Height; 01560 01561 DocRect BrushRect(BottomLeft, TopRight); 01563 // is there an intersection? If so add this point to the list 01564 if (BrushRect.IsIntersectedWith(Rect)) 01565 { 01566 PathPoint.m_Point = PointToCheck; 01567 PathPoint.m_Tangent = Angle; 01568 //TRACEUSER( "Diccon", _T("Adding point %d, %d\n"), PointToCheck.x, PointToCheck.y); 01569 m_ListOfPointsToRender.push_back( PathPoint ); 01570 } 01571 } 01572 // get the next distance 01573 DistanceToPoint += m_BrushSpacing; 01574 } 01575 } 01576 01577 01578 01579 /******************************************************************************************** 01580 01581 > void NodeBrushMaker::AddAllPointsToList() 01582 01583 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01584 Created: 6/10/99 01585 Inputs: - 01586 Outputs: - 01587 Returns: - 01588 Purpose: Adds all the points in the brush to the list of things to be rendered 01589 01590 ********************************************************************************************/ 01591 01592 void NodeBrushMaker::AddAllPointsToList() 01593 { 01594 // TRACEUSER( "Diccon", _T("\nAdding ALL points\n")); 01595 MILLIPOINT DistanceToPoint = 0; 01596 CPathPointInfo PathPoint; 01597 01598 while (DistanceToPoint < (m_MaxStep * m_BrushSpacing)) 01599 { 01600 double Angle; 01601 DocCoord Point; 01602 BOOL ok = m_pNodeBrushPath->GetPointAtDistance(DistanceToPoint, &Point, &Angle, m_bUsePathCache); 01603 if (ok) 01604 { 01605 PathPoint.m_Point = Point; 01606 PathPoint.m_Tangent = Angle; 01607 m_ListOfPointsToRender.push_back( PathPoint ); 01608 // //TRACEUSER( "Diccon", _T("Adding point %d, %d\n"), Point.x, Point.y); 01609 } 01610 // get the next distance 01611 DistanceToPoint += m_BrushSpacing; 01612 } 01613 01614 01615 } 01616 01617 01618 01619 /******************************************************************************************** 01620 01621 > void NodeBrushMaker::RenderBrushObjectAtPoint(CPathPointinfo Point, RenderRegion* pRender) 01622 01623 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01624 Created: 6/10/99 01625 Inputs: Point - co-ordinate where we wish to render the brush object 01626 pRender - the render region to render on to 01627 Outputs: - 01628 Returns: - 01629 Purpose: Renders a brush object at the point specified 01630 01631 ********************************************************************************************/ 01632 01633 void NodeBrushMaker::RenderBrushObjectAtPoint(CPathPointInfo Point, RenderRegion* pRender) 01634 { 01635 PORTNOTETRACE("other","NodeBrushMaker::RenderBrushObjectAtPoint - do nothing"); 01636 #ifndef EXCLUDE_FROM_XARALX 01637 pRender->SaveContext(); 01638 POSITION ListPosition = m_OffsetList.GetHeadPosition(); 01639 01640 Trans2DMatrix Trans; 01641 Trans2DMatrix Rotate; 01642 01643 BlendPath* pBlendPath = m_pBlendRef->GetFirstBlendPath(); 01644 CCAttrMap* pAttrMap = NULL; 01645 DocCoord CopyPoint; 01646 double RadToDeg = 1/ (2* PI); 01647 while (pBlendPath != NULL) 01648 { 01649 CopyPoint = SetPosition(Point, m_AltValue, &ListPosition); 01650 01651 //TRACEUSER( "Diccon", _T("Rendering at %d, %d\n"), Point.m_Point.x, Point.m_Point.y); 01652 01653 01654 01655 // find out where the blendpath is at the moment, and transate it 01656 // to where we are now 01657 DocRect BRect = pBlendPath->m_pPath->GetBoundingRect(); 01658 DocCoord CurrentPoint = BRect.Centre(); 01659 Trans.SetTransform(CopyPoint.x - CurrentPoint.x, CopyPoint.y - CurrentPoint.y ); 01660 if (m_bRotate) 01661 { 01662 double RotAngle = 360 *(Point.m_Tangent * RadToDeg); 01663 Rotate.SetTransform(CopyPoint, RotAngle); 01664 01665 //Trans.operator *=(Rotate); 01666 } 01667 // do randomisation if we need to 01668 if (m_bRandomizeShape) 01669 RandomizeShape(&Trans); 01670 01671 if (m_AttrRandomness > 0) 01672 RandomizeAttributes(); 01673 01674 01675 Trans.Transform( (DocCoord*)pBlendPath->m_pPath->GetCoordArray(), pBlendPath->m_pPath->GetNumCoords()); 01676 Rotate.Transform( (DocCoord*)pBlendPath->m_pPath->GetCoordArray(), pBlendPath->m_pPath->GetNumCoords()); 01677 pAttrMap = pBlendPath->FindAppliedAttributes(); 01678 if (pAttrMap == NULL) 01679 ERROR3("No applied attributes"); 01680 01681 if (!m_bTile) 01682 pAttrMap->Transform(Trans); 01683 else 01684 pAttrMap->TransformForBrush(Trans); 01685 01686 pAttrMap->Transform(Rotate); 01687 01688 RenderAttributes(pRender, pAttrMap); 01689 pRender->DrawPath(pBlendPath->m_pPath); 01690 m_BrushStep++; 01691 //TRACEUSER( "Diccon", _T("Rendering Object %d at %d, %d\n"), m_BrushStep, Point.x, Point.y); 01692 01693 pBlendPath = m_pBlendRef->GetNextBlendPath(pBlendPath); 01694 } 01695 pRender->RestoreContext(); 01696 #endif 01697 } 01698 01699 /******************************************************************************************** 01700 01701 > DocCoord NodeBrushMaker::SetPosition(CPathPointInfo OriginalPoint, UINT32 AltValue, 01702 POSITION ListPosition) 01703 01704 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01705 Created: 6/10/99 01706 Inputs: OriginalPoint - the point on the line at the correct distance for us to draw an object 01707 AltValue - if the offset it alternating then: 01708 0 = go right 01709 1 = go left 01710 ListPosition - the current position in the offset CList 01711 Outputs: POSITION is incremented. 01712 Returns: the new position where we wish the object to be drawn 01713 Purpose: To determine where the next brush object should be drawn. The position from the 01714 line can be altered by the following factors; 01715 01716 - m_OffsetList: Mostly used for brushes made from compound nodes. The list contains a 01717 translation for each BlendPath in m_Blendref showing how far it was from the centre of 01718 the bounding box of the original object. 01719 01720 - m_PathOffsetType and m_PathOffsetValue: These translations map the point on one side of 01721 the path or the other, the value determines exactly how far from the path they will be. 01722 01723 - m_PositionRandomness: introduces a random element to the position of the object 01724 SeeAlso: - 01725 01726 *********************************************************************/ 01727 01728 DocCoord NodeBrushMaker::SetPosition(CPathPointInfo OriginalPoint, UINT32 AltValue, 01729 CListOfPointsToRender::iterator *ListPosition ) 01730 { 01731 BlendPathOffset PointOffset; 01732 01733 if (*ListPosition != m_ListOfPointsToRender.end() ) 01734 { 01735 //PointOffset = m_OffsetList.GetNext(*ListPosition); 01736 OriginalPoint.m_Point.translate(PointOffset.m_XOffset, PointOffset.m_YOffset); 01737 } 01738 01739 double theta; 01740 double NewX; 01741 double NewY; 01742 01743 switch (m_PathOffsetType) 01744 { 01745 case OFFSET_NONE: 01746 break; 01747 case OFFSET_ALTERNATE: 01748 if (AltValue == 0) 01749 theta = OriginalPoint.m_Tangent - 90; 01750 else 01751 theta = OriginalPoint.m_Tangent + 90; 01752 01753 NewX = m_PathOffsetValue * cos (theta); 01754 NewY = m_PathOffsetValue * sin (theta); 01755 OriginalPoint.m_Point.translate((INT32)NewX, (INT32)NewY); 01756 break; 01757 case OFFSET_RIGHT: 01758 theta = OriginalPoint.m_Tangent - 90; 01759 NewX = m_PathOffsetValue * cos (theta); 01760 NewY = m_PathOffsetValue * sin (theta); 01761 OriginalPoint.m_Point.translate((INT32)NewX, (INT32)NewY); 01762 break; 01763 case OFFSET_LEFT: 01764 theta = OriginalPoint.m_Tangent + 90; 01765 NewX = m_PathOffsetValue * cos (theta); 01766 NewY = m_PathOffsetValue * sin (theta); 01767 OriginalPoint.m_Point.translate((INT32)NewX, (INT32)NewY); 01768 break; 01769 case OFFSET_RANDOM: 01770 break; 01771 default: 01772 ERROR3("Unknown offset type"); 01773 break; 01774 } 01775 01776 return OriginalPoint.m_Point; 01777 } 01778 01779 01780 01781 01782 01783 01784 01785 01786 01787 /******************************************************************************************** 01788 01789 > void NodeBrushMaker::SetStartCoord(DocCoord Coord) 01790 01791 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01792 Created: 6/10/99 01793 Inputs: the starting coordinate of the brush 01794 Outputs: - 01795 Returns: - 01796 Purpose: To set the starting coordinate of the brush 01797 SeeAlso: - 01798 01799 ********************************************************************************************/ 01800 01801 void NodeBrushMaker::SetStartCoord(DocCoord Coord) 01802 { 01803 m_StartCoord = Coord; 01804 } 01805 01806 01807 01808 01809 /******************************************************************************************** 01810 01811 > void NodeBrushMaker::SetGRenderBitmap(GRenderBitmap* pGRenderBitmap) 01812 01813 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01814 Created: 6/10/99 01815 Inputs: pointer to the bitmap to set 01816 Outputs: - 01817 Returns: - 01818 Purpose: To set the pointer to the 'big' bitmap used to store the view 01819 SeeAlso: - 01820 01821 ********************************************************************************************/ 01822 01823 void NodeBrushMaker::SetGRenderBitmap(GRenderBrush* pGRenderBitmap) 01824 { 01825 m_pGRenderDIB = (GRenderBrush*)pGRenderBitmap; 01826 } 01827 01828 01829 01830 /******************************************************************************************** 01831 01832 > void NodeBrushMaker::SetBlendRef(BlendRef* pBlendRef) 01833 01834 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01835 Created: 6/10/99 01836 Inputs: pointer to the blendref 01837 Outputs: - 01838 Returns: - 01839 Purpose: To set the used to generate the brush objects 01840 SeeAlso: - 01841 01842 ********************************************************************************************/ 01843 01844 void NodeBrushMaker::SetBlendRef(BlendRef* pBlendRef) 01845 { 01846 if (pBlendRef == NULL) 01847 { 01848 ERROR3("Blend ref is NULL"); 01849 return; 01850 } 01851 m_pBlendRef = pBlendRef; 01852 01853 DocRect BRect = pBlendRef->GetBoundingRect(); 01854 DocCoord InkCentre = BRect.Centre(); 01855 01856 m_OffsetList.clear(); 01857 01858 // if (ok) 01859 { 01860 // get the first blendpath as we need to pass it to the function 01861 // that retrieves the attributes 01862 BlendPath* pBlendPath = m_pBlendRef->GetFirstBlendPath(); 01863 if (pBlendPath == NULL) 01864 { 01865 ERROR3("First blendpath is NULL"); 01866 return; 01867 } 01868 01869 m_BrushBoundingRect = pBlendPath->m_pPath->GetBoundingRect(); 01870 while (pBlendPath != NULL) 01871 { 01872 // find out how far each blendpath is offset from the centre of 01873 // the bounding box and record it. 01874 DocRect BlendPathRect = pBlendPath->m_pPath->GetBoundingRect(); 01875 m_BrushBoundingRect = m_BrushBoundingRect.Union(BlendPathRect); 01876 01877 DocCoord BlendPathCentre = BlendPathRect.Centre(); 01878 BlendPathOffset ThisOffset; 01879 ThisOffset.m_XOffset = BlendPathCentre.x - InkCentre.x ; 01880 ThisOffset.m_YOffset = BlendPathCentre.y - InkCentre.y; 01881 //TRACEUSER( "Diccon", _T("Offset = %d, %d\n"), ThisOffset.m_XOffset, ThisOffset.m_YOffset); 01882 m_OffsetList.push_back( ThisOffset ); 01883 pBlendPath = m_pBlendRef->GetNextBlendPath(pBlendPath); 01884 } 01885 } 01886 01887 std::vector< BlendPathOffset >::iterator ListPosition = m_OffsetList.begin(); 01888 while (ListPosition != m_OffsetList.end()) 01889 { 01890 BlendPathOffset Offset = *(ListPosition++); 01891 TRACEUSER( "Diccon", _T("List offset %d, %d\n"), Offset.m_XOffset, Offset.m_YOffset); 01892 } 01893 01894 } 01895 01896 01897 01898 /******************************************************************************************** 01899 01900 > void NodeBrushMaker::RecalculateMaxStep() 01901 01902 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01903 Created: 6/10/99 01904 Inputs: - 01905 Outputs: - 01906 Returns: - 01907 Purpose: Recalculates the max step of the brush, call this when the path gets changed 01908 ********************************************************************************************/ 01909 01910 void NodeBrushMaker::RecalculateMaxStep() 01911 { 01912 if (m_pNodeBrushPath != NULL) 01913 { 01914 INT32 NewMaxStep = (INT32)(m_pNodeBrushPath->GetPathLength() / m_BrushSpacing); 01915 if (NewMaxStep > 0) 01916 { 01917 m_MaxStep = NewMaxStep; 01918 } 01919 else 01920 ERROR3("Negative number of steps calculated"); 01921 } 01922 } 01923 01924 01925 01926 01927 /******************************************************************************************** 01928 01929 > void NodeBrushMaker::ClearListOfPointsToRender() 01930 01931 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01932 Created: 6/10/99 01933 Inputs: - 01934 Outputs: - 01935 Returns: - 01936 Purpose: Clears out the cached list of points to render, ensures that all points will 01937 be rendered on the next Render 01938 ********************************************************************************************/ 01939 01940 void NodeBrushMaker::ClearListOfPointsToRender() 01941 { 01942 m_ListOfPointsToRender.clear(); 01943 }