brshcomp.cpp

Go to the documentation of this file.
00001 // $Id: brshcomp.cpp 1732 2006-09-03 14:08:16Z 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 // Brush Component and Brush Definition headers
00100 
00101 #include "camtypes.h"
00102 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 #include "brshcomp.h"
00105 #include "linecomp.h"
00106 //#include "colormgr.h"
00107 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "cxfrech.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "cxftags.h"
00110 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "layer.h"
00112 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "brushref.h"
00114 #include "freehand.h"
00115 #include "freeinfo.h"
00116 //#include "xlong.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 #include "ppbrush.h"
00118 #include "brshattr.h"
00119 #include "sgline.h"
00120 //#include "loadbrsh.h"
00121 #include "fileutil.h"
00122 #include "clipint.h"
00123 #include "nodebldr.h"
00124 #include "bldbrdef.h"
00125 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00126 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00127 #include "lineattr.h"
00128 #include "brshdata.h"
00129 //#include "swfrndr.h"
00130 #include "brshname.h"
00131 //#include "resdll.h"
00132 #include "nodeshad.h"
00133 #include "nodecntr.h"
00134 #include "nodebev.h"
00135 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00136 //#include "opdrbrsh.h"
00137 #include "toollist.h"
00138 //#include "freeinfo.h"
00139 #include "brshbeca.h"
00140 //#include "brdlgres.h"
00141 #include "brushop.h"
00142 
00143 DECLARE_SOURCE("$Revision: 1732 $");
00144 
00145 CC_IMPLEMENT_DYNAMIC(BrushDefinition, LineDefinition)
00146 CC_IMPLEMENT_DYNAMIC(BrushComponent, LineComponent)
00147 CC_IMPLEMENT_DYNAMIC(BrushComponentClass, DocComponentClass)
00148 
00149 // Declare smart memory handling in Debug builds
00150 #define new CAM_DEBUG_NEW  
00151 
00152 BOOL BrushComponent::m_bCancelNewBrush = FALSE;
00153 String_32 BrushComponent::m_NewName = TEXT("Unnamed brush");
00154 
00155 
00156 const INT32 MAX_TRANSP_VALUE = 255;
00157 /********************************************************************************************
00158 
00159 >   BrushDefinition::BrushDefinition(Node *pBrushTree);
00160 
00161     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00162     Created:    27/2/97
00163 
00164     Inputs:     pBrushTree - A pointer to a Spread node which is the root of a clipart
00165                               subtree which should be used for this Brush definition. It
00166                               must obey these rules:
00167                                 * It must be a Spread
00168                                 * It must not be linked into any other parent tree structure
00169                                 * It should contain at least one ink node (or else the Brush
00170                                   will appear "blank"). 
00171                                 * It should be attribute complete, or close thereto
00172 
00173     Purpose:    Constructor
00174 
00175     SeeAlso:    BrushComponent::AddNewBrush
00176 
00177 ********************************************************************************************/
00178 
00179 BrushDefinition::BrushDefinition(Node* pBrushTree) 
00180 : LineDefinition(pBrushTree)
00181 {
00182     ResetMembers();
00183     InitialiseBrushArray(MAX_BRUSH_OBJECTS);
00184     if (!GenerateBrush())
00185     {
00186         // hmm, not sure what to do here, but you can detect if we failed to initialise
00187         // by calling IsActivated, if that fails you should delete me.
00188     }
00189     
00190 }
00191 
00192 
00193 /********************************************************************************************
00194 
00195 >   BrushDefinition::BrushDefinition()
00196 
00197     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00198     Created:    27/2/97
00199 
00200     Purpose:    Default constructor for the purposes of inherited classes, if you just want a
00201                 normal brushdef you should really use the constructor above.  
00202             
00203                 5/12/2000 Actually I've just read that it is a poor idea to initialise inside
00204                 constructors, so I think that a reorganisation should occur whereby the construcotr
00205                 should simply assign the brush tree and we should GenerateBrush after the constructor
00206                 returns.
00207 
00208 ********************************************************************************************/
00209 
00210 BrushDefinition::BrushDefinition()
00211 {
00212     ResetMembers();
00213 }
00214 
00215 
00216 /********************************************************************************************
00217 
00218 >   BrushDefinition::~BrushDefinition()
00219 
00220     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00221     Created:    27/2/97
00222 
00223     Purpose:    Destructor
00224 
00225 ********************************************************************************************/
00226 
00227 BrushDefinition::~BrushDefinition()  
00228 { 
00229     for( size_t i = 0; i < m_BrushRefPtrArray.size(); i++ )
00230     {
00231         // ask the brushref to delete the attribute maps it generated
00232         if (m_BrushRefPtrArray[i] != NULL)
00233         {
00234         //  m_BrushRefPtrArray[i]->DeleteAttributeMapsAndAttributes();
00235             delete m_BrushRefPtrArray[i];
00236         }
00237     }
00238     m_BrushRefPtrArray.clear();
00239 
00240     
00241 
00242 }
00243 
00244 
00245 
00246 /***********************************************************************************************
00247 
00248 >   void BrushDefinition::ResetMembers()
00249 
00250     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00251     Created:    6/10/99
00252     Inputs:     -
00253     Returns     -
00254     Purpose:    Initialises the member variables
00255 
00256 ***********************************************************************************************/
00257 
00258 void BrushDefinition::ResetMembers()
00259 {
00260     m_BrushSpacing          = 10000;
00261     m_BrushSpacingIncrProp  = 1.0;
00262     m_BrushSpacingIncrConst = 0;
00263     m_BrushSpacingMaxRand   = 0;
00264     m_BrushSpacingRandSeed  = 0;
00265 
00266     m_PathOffsetType      = OFFSET_NONE;
00267     m_PathOffsetValue     =  0;
00268     m_PathOffsetIncrProp  = 1.0;
00269     m_PathOffsetIncrConst = 0;
00270     m_OffsetTypeRandSeed  = 0;
00271     m_OffsetValueMaxRand  = 0;
00272     m_OffsetValueRandSeed = 0;
00273 
00274     m_bRotate             = TRUE;
00275     m_RotateAngle         = 0;
00276     m_RotationMaxRand     = 0;
00277     m_RotationRandSeed    = 0;
00278     m_RotAngleIncrConst   = 0;
00279     m_RotAngleIncrProp    = 1.0;
00280     m_RotationMaxPressure = 0;
00281 
00282     m_bTile               = TRUE;
00283 
00284     m_BrushScaling        = 1.0;
00285     m_BrushScalingIncr    = 1.0;
00286     m_BrushScalingIncrConst = 0.0;
00287     m_BrushScalingMaxRand   = 0;
00288     m_BrushScalingRandSeed  = 0;
00289     m_ScalingMaxPressure    = 35;
00290     
00291     m_BrushHueIncrement     = 0.0;
00292     m_BrushHueMaxRand       = 0;
00293     m_BrushHueRandSeed      = 1234;
00294 
00295     m_BrushSatIncrement     = 0.0;
00296     m_BrushSatMaxRand       = 0;
00297     m_BrushSatRandSeed      = 5432; 
00298 
00299     m_SequenceType        = SEQ_FORWARD;
00300     m_SequenceRandSeed    = 0;
00301 
00302     m_NumBrushObjects     = 0;
00303     m_bInitOk             = FALSE;
00304 
00305     m_LargestBoundingBox.MakeEmpty();
00306 
00307     m_Name = TEXT("Custom Brush");
00308 
00309     m_TimeStampPeriod = 0;
00310 
00311     m_BrushTransparency  = 100;
00312     m_TranspMaxPressure  = 0;
00313 
00314     m_DefaultFileID = BRUSHFILE_NONE;
00315 
00316     m_bActivated = FALSE;
00317 }
00318 
00319 
00320 
00321 /***********************************************************************************************
00322 
00323 >   BOOL BrushDefinition::GenerateBrush()
00324 
00325     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00326     Created:    13/12/99
00327     Inputs:     -
00328     Returns     TRUE if successful, FALSE otherwise
00329     Purpose:    goes through the input spread and calls AddNewObject() for each ink object found
00330                 We try to make some intelligent guesses about what to set the starting spacing and
00331                 offset values depending on the nature of the nodes.  The following rules apply:
00332                 - if there are multiple ink objects then the spacing is 1.1 * the largest dimension 
00333                 of the largest bounding box
00334                 - if there is only one object and it contains a positive line width spacing is as above
00335                 - if there is only one object with no line width then spacing is 10000 millipoint
00336                 - defaulf offset is always the largest dimension of the largest BBOX.
00337 
00338 ***********************************************************************************************/
00339 
00340 BOOL BrushDefinition::GenerateBrush()
00341 {
00342     if (m_pTree == NULL)
00343         return FALSE;
00344 
00345     // get a node that points at the first child of the layer
00346     Node* pNode = m_pTree->FindFirstChild();
00347     pNode       = pNode->FindFirstChild();
00348     
00349 
00350     AttrLineWidth* pLineWidth = NULL;
00351     while (pNode != NULL)
00352     {
00353         if (pNode->IsAnObject())
00354         {
00355             // it has been drawn to my attention that it is possible to end up with a brush object
00356             // that has no line width attribute, which leads to all kinds of problems.  So here we will
00357             // search for one and if we don't find one we will add one.
00358             ((NodeRenderableInk*)pNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrLineWidth), (NodeAttribute**)&pLineWidth);
00359             if (!pLineWidth)
00360             {
00361                 pLineWidth = new AttrLineWidth(pNode, LASTCHILD);
00362                 if (pLineWidth)
00363                 {
00364                     pLineWidth->Value.LineWidth = 501;
00365                     pLineWidth = NULL;
00366                 }
00367             }
00368 
00369             // we don't want to make brushes from brushes, instead we want to convert them
00370             // to shapes first, so use the routine to do that.
00371             NodeGroup* pGroup = NULL;
00372             ReplaceBrushWithGroup((NodeRenderableInk*)pNode, &pGroup);
00373             if (pGroup != NULL)
00374             {
00375                 // we got a group, so we have to delete the original node
00376                 pGroup->AttachNode(pNode, NEXT);
00377                 pGroup->FactorOutCommonChildAttributes();
00378                 // unhook from the tree
00379                 pNode->CascadeDelete();
00380 
00381                 // swap the pointers
00382                 Node* pDelete = pNode;
00383                 pNode = pGroup;
00384                 
00385                 delete pDelete;
00386             }
00387 
00388             if (!AddNewObject((NodeRenderableInk*)pNode))
00389                 return FALSE;
00390         }
00391         pNode = pNode->FindNext();
00392     }
00393     CalculateMaxScaling();
00394 
00395     m_bActivated = TRUE;
00396     return TRUE;
00397 
00398 }
00399 
00400 
00401 /***********************************************************************************************
00402 
00403 >   BOOL BrushDefinition::ReplaceBrushWithGroup(NodeRenderableInk* pInk, NodeGroup* pGroup)
00404 
00405     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00406     Created:    13/12/99
00407     Inputs:     pInk - the inknode that we are going to generate a brush from
00408     Outputs:    if pInk has a brush attribute applied to it then we will generate a new group 
00409                 from that brush
00410     Returns     TRUE if successful, FALSE otherwise
00411     Purpose:    We are no longer allowed to make brushes from brushes, because of problems
00412                 when saving and loading.  Instead if we have a brush then we will convert
00413                 it to shapes and use those instead.
00414 
00415     Note:       So you actually have to delete pInk yourself if this function outputs a group.
00416                 I had to do that to get the recursion to work.  Still I'm sure you can handle it.
00417 ***********************************************************************************************/
00418 
00419 BOOL BrushDefinition::ReplaceBrushWithGroup(NodeRenderableInk* pInk, NodeGroup** ppGroup)
00420 {
00421     ERROR2IF(pInk == NULL, FALSE, "Invalid inputs to BrushDefinition::ReplaceBrushWithGroups");
00422 
00423     BOOL  ok = TRUE;
00424     // if we're compound then search through all our children first
00425     if (pInk->IsCompound())
00426     {
00427         NodeGroup* pNodeGroup = NULL;
00428         Node* pChild = pInk->FindFirstChild();
00429         Node* pDelete = NULL;       
00430         
00431         while (pChild)
00432         {
00433             if (pChild->IsAnObject())
00434             {
00435                 if (ok) ok = ReplaceBrushWithGroup((NodeRenderableInk*)pChild, &pNodeGroup);
00436                 if (pNodeGroup)
00437                 {
00438                     // attach the new group next to the child
00439                     pNodeGroup->AttachNode(pChild, NEXT);
00440 
00441                     pNodeGroup->FactorOutCommonChildAttributes();
00442 
00443                     // unhook the child
00444                     pChild->CascadeDelete();
00445                     
00446                     // we're ready to delete the original child
00447                     pDelete =  pChild;
00448 
00449                     // swap the pointer
00450                     pChild = pNodeGroup;    
00451 
00452                     delete pDelete;
00453                 }
00454             }
00455             pChild = pChild->FindNext();
00456             pNodeGroup = NULL;
00457         }
00458     }
00459 
00460     AttrBrushType* pAttrBrush = NULL;
00461     pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), (NodeAttribute**)&pAttrBrush);
00462 
00463     if (pAttrBrush && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush && ok)
00464     {
00465         //Turn the brush into a group with lots of nodepaths
00466         BrushBecomeAGroup BecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), NULL);
00467         ok = pAttrBrush->DoBecomeA(&BecomeA, pInk);
00468 
00469         // the brush will create a group out of itself and we want to retrieve that
00470         NodeGroup* pBrushGroup = BecomeA.GetNodeGroup();
00471         pBrushGroup->FactorOutCommonChildAttributes();
00472         pBrushGroup->NormaliseAttributes();
00473         if (pBrushGroup != NULL && ok)
00474         {
00475             *ppGroup = pBrushGroup;
00476         }
00477     }
00478     return ok;
00479 }
00480 
00481 /***********************************************************************************************
00482 
00483 >   BOOL BrushDefinition::RegenerateBrush()
00484 
00485     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00486     Created:    13/12/99
00487     Inputs:     -
00488     Returns     TRUE if successful, FALSE otherwise
00489     Purpose:    This function deletes the existing brushrefs and recreates them from scratch from 
00490                 m_pTree.
00491 
00492     Notes:      This function is necessary because of the inaccuracies in our matrix transformation
00493                 system which make it impossible to repeatedly scale without either growing our objects.
00494                 Therefore it is recommended that after every render where an object is scaled this function
00495                 should be called to regenerate the brush.
00496                 Obviously the potential for disaster is very high for instance we run out of memory
00497                 in the middle of the operation.
00498 
00499 ***********************************************************************************************/
00500 
00501 BOOL BrushDefinition::RegenerateBrush()
00502 {
00503     /*  As we now always take copies of the brush objects, this is scheduled for demolition...
00504 
00505     // first we need to transform all the attributes back to where they began
00506     PreExportSubTree();
00507 
00508     // make a temporary array to hold the existing elements, as we do not wish 
00509     // to delete them until we are sure regeneration went ok
00510     CTypedPtrArray <CPtrArray, BrushRef*> TempArray;
00511     
00512     TempArray.SetSize(MAX_BRUSH_OBJECTS, -1);
00513 
00514     // fill the array with our existing objects
00515     BrushRef* pRef = NULL;
00516     INT32 i = 0;
00517     for (i = 0; i < TempArray.GetSize(); i++)
00518     {
00519         pRef = m_BrushRefPtrArray[i];
00520         TempArray.SetAt(i, pRef);
00521         m_BrushRefPtrArray.SetAt(i, NULL); // set existing pointer to null
00522     }
00523 
00524     m_NumBrushObjects = 0;
00525 
00526     // now remake ourselves
00527     if  (GenerateBrush() == TRUE)
00528     {
00529         // delete the existing brushrefs
00530         for (i = 0; i < TempArray.GetSize(); i++)
00531         {
00532             if (TempArray[i] != NULL)
00533             {
00534                 delete TempArray[i];
00535             }
00536         }
00537         TempArray.RemoveAll();
00538         
00539         return TRUE;
00540     }
00541 
00542     // ok so something went wrong, not much we can do except for restore the original objects
00543     // and hope for the best
00544     ERROR3("Uh oh - Regenerate Brush failed");
00545     pRef = NULL;
00546     i= 0;
00547     for (i = 0; i < TempArray.GetSize(); i++)
00548     {
00549         pRef = TempArray[i];
00550         m_BrushRefPtrArray.SetAt(i, pRef); // set existing pointer to null
00551         TempArray[i] = NULL;
00552     }
00553     */
00554     return TRUE;
00555 }
00556 
00557 
00558 
00559 /***********************************************************************************************
00560 
00561 >   BOOL BrushDefinition::IsActivated()
00562 
00563     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00564     Created:    13/12/99
00565     Inputs:     -
00566     Returns     the member indicating whether this definition is active
00567     Purpose:    To see if this definition was initialised ok or if it was subsequently deactivated
00568                 for some reason
00569 
00570 ***********************************************************************************************/
00571 
00572 BOOL BrushDefinition::IsActivated()
00573 {
00574     return m_bActivated;
00575 }
00576 
00577 
00578 /***********************************************************************************************
00579 
00580 >   void BrushDefinition::SetActivated(BOOL Value)
00581 
00582     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00583     Created:    13/12/99
00584     Inputs:     Value - the value to set
00585     Returns     -
00586     Purpose:    To set this definition activated or not
00587 
00588 ***********************************************************************************************/
00589 
00590 void BrushDefinition::SetActivated(BOOL Value)
00591 {
00592     m_bActivated = Value;
00593 }
00594 
00595 /***********************************************************************************************
00596 
00597 >   BOOL BrushDefinition::AddNewObject(NodeRenderableInk* pInkNode)
00598 
00599     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00600     Created:    13/12/99
00601     Inputs:     pInkNode - node to add
00602     Returns     TRUE if successful, FALSE otherwise
00603     Purpose:    creates a brushref object from the inknode and its attributes, then adds the
00604                 brushref to the member array
00605 
00606 ***********************************************************************************************/
00607 
00608 BOOL BrushDefinition::AddNewObject(NodeRenderableInk* pInkNode)
00609 {
00610 
00611     if (pInkNode == NULL)
00612     {
00613         ERROR3("Ink node is NULL");
00614         return FALSE;
00615     }
00616 
00617     if (m_NumBrushObjects >= MAX_BRUSH_OBJECTS)
00618     {
00619         ERROR3("Cannot exceed MAX_BRUSH_OBJECTS");
00620         return FALSE;
00621     }
00622 
00623     BrushRef *pNewBrushRef = new BrushRef;
00624 
00625     if (pNewBrushRef == NULL)
00626     {
00627         ERROR3("Failed to allocate brushref");
00628         return FALSE;
00629     }
00630     
00631 
00632     
00633     if (!pNewBrushRef->Initialise(pInkNode))
00634     {
00635         ERROR3("Failed to initialise brushref");
00636         return FALSE;
00637     }
00638 
00639     m_BrushRefPtrArray[m_NumBrushObjects++] = pNewBrushRef;
00640 
00641     return TRUE;
00642 
00643 }
00644 
00645 
00646 /***********************************************************************************************
00647 
00648 >   void BrushDefinition::InitialiseBrushArray(UINT32 NumObjects)
00649 
00650     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00651     Created:    6/10/99
00652     Inputs:     Number of objects to size the array at
00653     Returns:    -
00654     Purpose:    Clears out the m_BrushRefPtrArray if it is not empty, and sets the size 
00655 
00656 ***********************************************************************************************/
00657 
00658 void BrushDefinition::InitialiseBrushArray(UINT32 NumObjects) 
00659 {
00660     size_t              i = 0;
00661     while( i < m_BrushRefPtrArray.size() )
00662     {
00663         delete m_BrushRefPtrArray[i++];
00664     }
00665     m_BrushRefPtrArray.clear();
00666 
00667     m_BrushRefPtrArray.resize( NumObjects );
00668 
00669     // fill the array with NULL objects so that we can check later
00670     // to see if our allocations have worked
00671     i = 0;
00672     while( i < m_BrushRefPtrArray.size() )
00673     {
00674         m_BrushRefPtrArray[i++] = NULL;
00675     }
00676 
00677 }
00678 
00679 
00680 /********************************************************************************************
00681 
00682 >   BOOL BrushDefinition::IsDifferent(BrushDefinition *pOther)
00683 
00684     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00685     Created:    13/12/99
00686 
00687     Inputs:     pOther - the Brush to compare this Brush to
00688 
00689     Returns:    TRUE if they're different in any way,
00690                 FALSE if they are identical definitions
00691 
00692     Purpose:    Determine if 2 BrushDefinitions are considered different.
00693                 Used when adding Brushes to the global list, so that like Brushes
00694                 can be merged.
00695 
00696 ********************************************************************************************/
00697 
00698 BOOL BrushDefinition::IsDifferent(LineDefinition *pOther)
00699 {
00700     ERROR3IF(pOther == NULL, "Illegal NULL param");
00701 
00702 //  String_32* pName = pOther->GetLineName();
00703     if (!m_Name.IsIdentical(*pOther->GetLineName()))
00704         return(TRUE);
00705 
00706     if (pOther->GetLineTree() == NULL || m_pTree == NULL)
00707     {
00708         ERROR3("BrushDefinition has not been properly initialised");
00709         return(TRUE);
00710     }
00711 
00712     /*
00713     // --- Check to see if the brush bounds are equal
00714     DocRect OtherBounds = ((Spread *)(pOther->GetLineTree()))->GetBoundingRect();
00715     DocRect Bounds = ((Spread *)m_pTree)->GetBoundingRect();
00716     if (Bounds != OtherBounds)
00717         return(TRUE);
00718     */
00719     // --- Check the subtrees node-for-node to see if they are the same
00720     Node *pCurNode1 = m_pTree->FindFirstDepthFirst();
00721     Node *pCurNode2 = pOther->GetLineTree()->FindFirstDepthFirst();
00722 
00723     while (pCurNode1 != NULL && pCurNode2 != NULL)
00724     {
00725         // if they are fill attributes then we want to translate both attributes to the origin.
00726         // This prevents us getting duplication of brushes when we have the 
00727         // same thing in a different place, note that occasionally this fails due to rounding errors.
00728         if (pCurNode1->IsAFillAttr() && pCurNode2->IsAFillAttr() && 
00729             !((AttrFillGeometry*)pCurNode1)->IsAStrokeColour() && 
00730             !((AttrFillGeometry*)pCurNode1)->IsAStrokeTransp())
00731         {
00732             AttrFillGeometry* pFill1 = (AttrFillGeometry*)pCurNode1;
00733             AttrFillGeometry* pFill2 = (AttrFillGeometry*)pCurNode2;
00734             DocCoord* pStartPoint1 = pFill1->GetStartPoint();
00735             DocCoord* pStartPoint2 = pFill2->GetStartPoint();
00736         
00737             // translate them both to 0,0
00738             if (pStartPoint1 && pStartPoint2)
00739             {
00740                 Trans2DMatrix Trans1(-pStartPoint1->x, -pStartPoint1->y);
00741                 Trans2DMatrix Trans2(-pStartPoint2->x, -pStartPoint2->y);
00742                 pFill1->Transform(Trans1);
00743                 pFill2->Transform(Trans2);
00744                 BOOL Different = FALSE;
00745                 if (pCurNode1->IsDifferent(pCurNode2))
00746                     Different = TRUE;
00747 
00748                 Trans1.Invert();
00749                 Trans2.Invert();
00750                 pFill1->Transform(Trans1);
00751                 pFill2->Transform(Trans2);
00752                 if (Different == TRUE)
00753                     return TRUE;
00754             }
00755 
00756         }
00757         else
00758             // likewise if they are an object then translate from the centre of the bounding
00759             // rect to the origin
00760             if (pCurNode1->IsAnObject() && pCurNode2->IsAnObject())
00761             {
00762                 NodeRenderableInk* pInk1 = (NodeRenderableInk*)pCurNode1;
00763                 NodeRenderableInk* pInk2 = (NodeRenderableInk*)pCurNode2;
00764                 DocRect BRect1 = ((NodeRenderableInk*)pCurNode1)->GetBoundingRect();
00765                 DocRect BRect2 = ((NodeRenderableInk*)pCurNode2)->GetBoundingRect();
00766                 DocCoord Coord1 = BRect1.Centre();
00767                 DocCoord Coord2 = BRect2.Centre();
00768                 Trans2DMatrix Trans1(-Coord1.x, -Coord1.y);
00769                 Trans2DMatrix Trans2(-Coord2.x, -Coord2.y);
00770                 pInk1->Transform(Trans1);
00771                 pInk2->Transform(Trans2);
00772                 BOOL Different = FALSE;
00773                 if (pCurNode1->IsDifferent(pCurNode2))
00774                     Different = TRUE;
00775                 
00776                 Trans1.Invert();
00777                 Trans2.Invert();
00778                 pInk1->Transform(Trans1);
00779                 pInk2->Transform(Trans2);
00780                 if (Different ==TRUE)
00781                     return TRUE;
00782             }
00783         else 
00784         {
00785             // otherwise just use the regular == operator
00786             if (pCurNode1->IsDifferent(pCurNode2))
00787                 return(TRUE);
00788         }
00789 
00790         // And go to the next node in both brushes
00791         pCurNode1 = pCurNode1->FindNextDepthFirst(m_pTree);
00792         pCurNode2 = pCurNode2->FindNextDepthFirst(pOther->GetLineTree());
00793     }
00794 
00795     if (!AreBrushParametersIdentical((BrushDefinition*)pOther))
00796         return TRUE;
00797 
00798     // If we did the entire search and both pointers ended up NULL simultaneously, then
00799     // we have an exact match
00800     if (pCurNode1 == NULL && pCurNode2 == NULL)
00801         return(FALSE);
00802 
00803     return(TRUE);
00804 }
00805 
00806 
00807 /********************************************************************************************
00808 
00809 >   BOOL BrushDefinition::IsDifferent(BrushDefinition *pOther)
00810 
00811     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00812     Created:    13/12/99
00813 
00814     Inputs:     pOther - the Brush to compare this Brush to
00815 
00816     Returns:    TRUE if they're different 
00817                 FALSE if they are identical 
00818 
00819     Purpose:    Compares the member variables of the two brushes
00820 
00821 ********************************************************************************************/
00822 
00823 BOOL BrushDefinition::AreBrushParametersIdentical(BrushDefinition* pOther)
00824 {
00825     if (m_BrushSpacing          != pOther->m_BrushSpacing           ||
00826         m_BrushSpacingIncrProp  != pOther->m_BrushSpacingIncrProp   ||
00827         m_BrushSpacingIncrConst != pOther->m_BrushSpacingIncrConst  ||
00828         m_BrushSpacingMaxRand   != pOther->m_BrushSpacingMaxRand    ||
00829         m_BrushSpacingRandSeed  != pOther->m_BrushSpacingRandSeed   ||
00830         m_SpacingMaxPressure    != pOther->m_SpacingMaxPressure     ||
00831         
00832         m_bTile                 != pOther->m_bTile                  ||
00833         m_bRotate               != pOther->m_bRotate                ||
00834         
00835         m_RotateAngle           != pOther->m_RotateAngle            ||
00836         m_RotAngleIncrProp      != pOther->m_RotAngleIncrProp       ||
00837         m_RotAngleIncrConst     != pOther->m_RotAngleIncrConst      ||
00838         m_RotationMaxRand       != pOther->m_RotationMaxRand        ||
00839         m_RotationRandSeed      != pOther->m_RotationRandSeed       ||
00840         m_RotationMaxPressure   != pOther->m_RotationMaxPressure    ||
00841 
00842         m_PathOffsetType        != pOther->m_PathOffsetType         ||
00843         m_PathOffsetValue       != pOther->m_PathOffsetValue        ||
00844         m_PathOffsetIncrProp    != pOther->m_PathOffsetIncrProp     ||
00845         m_PathOffsetIncrConst   != pOther->m_PathOffsetIncrConst    ||
00846         m_OffsetTypeRandSeed    != pOther->m_OffsetTypeRandSeed     ||
00847         m_OffsetValueMaxRand    != pOther->m_OffsetValueMaxRand     ||
00848         m_OffsetValueRandSeed   != pOther->m_OffsetValueRandSeed    ||
00849         
00850         m_BrushScaling          != pOther->m_BrushScaling           ||
00851         m_BrushScalingIncr      != pOther->m_BrushScalingIncr       ||
00852         m_BrushScalingIncrConst != pOther->m_BrushScalingIncrConst  ||
00853         m_BrushScalingMaxRand   != pOther->m_BrushScalingMaxRand    ||
00854         m_BrushScalingRandSeed  != pOther->m_BrushScalingRandSeed   ||
00855         m_ScalingMaxPressure    != pOther->m_ScalingMaxPressure     ||
00856 
00857         m_BrushHueIncrement     != pOther->m_BrushHueIncrement      ||
00858         m_BrushHueMaxRand       != pOther->m_BrushHueMaxRand        ||
00859         m_BrushHueRandSeed      != pOther->m_BrushHueRandSeed       ||
00860         m_HueMaxPressure        != pOther->m_HueMaxPressure         ||
00861 
00862         m_BrushSatIncrement     != pOther->m_BrushSatIncrement      ||
00863         m_BrushSatMaxRand       != pOther->m_BrushSatMaxRand        ||
00864         m_BrushSatRandSeed      != pOther->m_BrushSatRandSeed       ||
00865         m_SatMaxPressure        != pOther->m_SatMaxPressure         ||
00866 
00867         m_SequenceType          != pOther->m_SequenceType           ||
00868         m_SequenceRandSeed      != pOther->m_SequenceRandSeed       ||
00869 
00870         m_TimeStampPeriod       != pOther->m_TimeStampPeriod)
00871         return FALSE;
00872     else
00873         return TRUE;
00874 }
00875 
00876 
00877 /********************************************************************************************
00878 
00879 >   BrushDefinition* BrushDefinition::Copy()
00880 
00881     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00882     Created:    22/5/2000
00883 
00884     Inputs:     -
00885 
00886     Returns:    Pointer to new brush definition if succesful, NULL if it fails
00887     Purpose:    Makes a copy of this definition, inknodes and all.
00888     
00889 ********************************************************************************************/
00890 
00891 BrushDefinition* BrushDefinition::Copy()
00892 {   
00893     // we need to make a range in order to copy the nodes to the new brush definition
00894     // so we need the start and end nodes of the range
00895     Node* pStart = NULL;
00896     Node* pNext = NULL;
00897     Node* pLast = NULL;
00898 
00899     // don't forget we start on a spread
00900     Node* pTree = GetLineTree();
00901     if (pTree != NULL)
00902         pTree = pTree->FindFirstChild();  // get the layer
00903     if (pTree != NULL)
00904             pTree = pTree->FindFirstChild();  // get the first ink object
00905     
00906     if (pTree == NULL)
00907     {
00908         ERROR3("Tree node is NULL in BrushDefinition::Copy()");
00909         return NULL;
00910     }
00911     
00912     pNext = pStart = pTree;
00913     while (pNext != NULL)
00914     {
00915         pNext->SetSelected(FALSE);  // we need to do this so that Range::FindFirst doesn't return NULL
00916         pLast = pNext;
00917         pNext = pLast->FindNext();
00918     }
00919 
00920 
00921     // make a range out of our subtree as thats the easiest way to copy all the nodes
00922     RangeControl rc;
00923     rc.Unselected = TRUE;
00924     rc.Selected = FALSE;
00925     Range BrushRange(pStart, pLast, rc);
00926     
00927     // make a new spread to attach our copy tree to
00928     Spread* pSpread = new Spread;
00929     if (pSpread == NULL)
00930     {
00931         ERROR3("Failed to allocate spread in BrushDefinition::Copy");
00932         return NULL;
00933     }
00934 
00935     Layer              *pLayer = new Layer( pSpread, FIRSTCHILD, String_256( TEXT("Diccon did this") ) );
00936     if (pLayer == NULL)
00937     {
00938         ERROR3("Failed to allocate layer in BrushDefinition::Copy");
00939         delete pSpread;
00940         return NULL;
00941     }
00942 
00943     // we need to reset our attributes in the same way that we need to with exporting.
00944     // If we don't do this then attributes with control points end up vanishing
00945     PreExportSubTree();
00946 
00947     if (!pLayer->CopyComplexRange(BrushRange))
00948     {
00949         ERROR3("Failed to copy range in BrushDefinition::Copy");
00950         delete pSpread;
00951         delete pLayer;
00952         return NULL;
00953     }
00954 
00955     PostExportSubTree();
00956 
00957     // lets allocate ourselves a new empty definition
00958     BrushDefinition* pNewBrushDef = new BrushDefinition(pSpread);
00959 
00960     if (pNewBrushDef == NULL)
00961     {
00962         ERROR3("Failed to allocate brush definition in BrushDefinition* BrushDefinition::Copy");
00963         delete pSpread;
00964         delete pLayer;
00965         return NULL;
00966     }
00967 
00968     if (!pNewBrushDef->IsActivated())
00969     {
00970         ERROR3("Brush definition failed to initialise");
00971         delete pNewBrushDef;
00972         delete pSpread;
00973         delete pLayer;
00974         return NULL;
00975     }
00976 
00977     return pNewBrushDef;
00978 }
00979 
00980 /***********************************************************************************************
00981 
00982 >   BOOL BrushDefinition::UsesPressure()
00983 
00984     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
00985     Created:    16/6/2000
00986     Inputs:     -
00987     Returns     TRUE if this brush has one of its pressure variables set
00988     Purpose:    as above
00989 ***********************************************************************************************/
00990 
00991 BOOL BrushDefinition::UsesPressure()
00992 {
00993     if (m_ScalingMaxPressure != 0  ||
00994         m_RotationMaxPressure != 0 ||
00995         m_TranspMaxPressure != 0)
00996         return TRUE;
00997 
00998     return FALSE;
00999 }
01000 
01001 
01002 /***********************************************************************************************
01003 
01004 >   static BOOL BrushDefinition::ObjectCanCreateBrush(NodeRenderableInk* pObject)
01005 
01006     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
01007     Created:    16/6/2000
01008     Inputs:     pObject - the object to test
01009     Returns     TRUE if we are allowed to make a brush out of this object, FALSE otherwise
01010     Purpose:    To determine if this ink node can be made into a brush, currently returns TRUE for
01011                 except for bevels, shadows, and contours, which are too damn awkward.
01012 ***********************************************************************************************/
01013 
01014 BOOL BrushDefinition::ObjectCanCreateBrush(NodeRenderableInk* pObject)
01015 {
01016     ERROR2IF(pObject == NULL, FALSE, "Object is NULL in BrushDefinition::ObjectCanCreateBrush");
01017 
01018     // only way to do it is some ugly IKO's
01019     if (pObject->IS_KIND_OF(NodeShadow))
01020         return FALSE;
01021     if (pObject->IS_KIND_OF(NodeContour))
01022         return FALSE;
01023     if (pObject->IS_KIND_OF(NodeBevel))
01024         return FALSE;
01025 
01026     // if its compound then check all the children
01027     if (pObject->IsCompound())
01028     {
01029         Node* pChild = pObject->FindFirstChild();
01030         while (pChild)
01031         {
01032             if (pChild->IsAnObject())
01033             {
01034                 if (!ObjectCanCreateBrush((NodeRenderableInk*)pChild))
01035                     return FALSE;
01036             }
01037             pChild = pChild->FindNext();
01038         }
01039     }
01040 
01041     return TRUE;
01042 
01043 }
01044 
01045 
01046 /*********************************************************************************************
01047 
01048 >    BOOL BrushDefinition::StartRender()
01049 
01050      Author:    Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01051      Created:   4/9/2000
01052      Inputs:    -
01053      Outputs:   -
01054      Returns:   TRUE if successful, FALSE if not.  If we return FALSE then don't even think
01055                 about rendering with this brush.
01056 
01057      Purpose:   Basically due to imprecision in the arithmetic system we ended up corrupting the
01058                 brush data if we used it too much.  So to get around this we never transform
01059                 the original brush data, instead we make copies of it each time we want to render
01060                 a version of this brush.
01061                 This function generates the data copies that we need to render this brush, make 
01062                 sure you call StopRender() to get rid of them.
01063 **********************************************************************************************/
01064        
01065 BOOL BrushDefinition::StartRender()
01066 {
01067     BrushRef* pBrushRef = GetFirstBrushRef();
01068     BOOL ok = TRUE;
01069     while (pBrushRef != NULL)
01070     {
01071         if (ok)
01072             ok = pBrushRef->MakeCopiesForRendering();
01073         pBrushRef = GetNextBrushRef();
01074     }
01075 
01076     return ok;
01077     
01078 }
01079 
01080 
01081 
01082 /*********************************************************************************************
01083 
01084 >    void BrushDefinition::StopRender()
01085 
01086      Author:    Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01087      Created:   4/9/2000
01088      Inputs:    -
01089      Outputs:   -
01090      Returns:   -
01091 
01092      Purpose:   Call this when you have finished rendering a node with this brush, it deletes
01093                 the copied data that we used for rendering
01094 **********************************************************************************************/
01095        
01096 void BrushDefinition::StopRender()
01097 {
01098     BrushRef* pBrushRef = GetFirstBrushRef();
01099     while (pBrushRef != NULL)
01100     {
01101         pBrushRef->DeleteRenderCopies();
01102         pBrushRef = GetNextBrushRef();
01103     }
01104 
01105     return;
01106 
01107 }
01108 
01109 /***********************************************************************************************
01110 
01111 >   void BrushDefinition::CalculateMaxScaling()
01112 
01113     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
01114     Created:    13/12/99
01115     Inputs:     -
01116     Returns     -
01117     Purpose:    Calculates the maximum scaling value possible by dividing the maximum size value by
01118                 the longest side of the bounding rect of the largest object
01119 ***********************************************************************************************/
01120 
01121 void BrushDefinition::CalculateMaxScaling()
01122 {
01123     DocRect BRect = GetLargestBoundingBox();
01124     if (BRect.IsEmpty())
01125     {
01126         //ERROR3("Bounding rect is empty in BrushDefinition::CalculateMaxScaling");
01127         return;
01128     }
01129     MILLIPOINT LongestSide = BRect.Height() > BRect.Width() ? BRect.Height() : BRect.Width();
01130     m_MaxScaling = MAX_BRUSH_SIZE  / LongestSide;
01131 
01132 }
01133 
01134 
01135 /***********************************************************************************************
01136 
01137 >   double BrushDefinition::GetMaxScaling()
01138 
01139     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
01140     Created:    13/12/99
01141     Inputs:     -
01142     Returns     the maximum scaling value
01143     Purpose:    as above
01144 ***********************************************************************************************/
01145 
01146 double BrushDefinition::GetMaxScaling()
01147 {
01148     return m_MaxScaling;
01149 }
01150 
01151 /********************************************************************************************
01152 
01153 >   BOOL BrushDefinition::SetBrushSpacing(double Spacing) 
01154 
01155     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01156     Created:    6/10/99
01157     Inputs:     the spacing value to set
01158     Returns:    TRUE if successful, FALSE if the spacing is invalid 
01159     Purpose:    To set the spacing between brush objects
01160     SeeAlso:    -
01161 
01162 ********************************************************************************************/
01163 
01164 BOOL BrushDefinition::SetSpacing(MILLIPOINT Spacing)
01165 {
01166     if (Spacing < MIN_BRUSH_SPACING || Spacing > MAX_BRUSH_SPACING)
01167         return FALSE;
01168     
01169     m_BrushSpacing = Spacing;
01170 
01171     return TRUE;
01172 
01173 }
01174 
01175 
01176 
01177 /********************************************************************************************
01178 
01179 >   MILLIPOINT BrushDefinition::GetBrushSpacing() 
01180 
01181     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01182     Created:    6/10/99
01183     Returns:    the spacing between the brush objects 
01184     Purpose:    As above
01185 
01186 ********************************************************************************************/
01187 
01188 MILLIPOINT BrushDefinition::GetSpacing()
01189 {
01190     return m_BrushSpacing;
01191 }
01192 
01193 
01194 
01195 /********************************************************************************************
01196 
01197 >   BOOL PathProcessorBrush::SetSpacingIncrProp(double Incr) 
01198 
01199     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01200     Created:    6/10/99
01201     Inputs:     the spacing increment value to set
01202     Returns:    TRUE if we can draw 10 objects, FALSE if the spacing is invalid 
01203     Purpose:    To set the proportional spacing increment between brush objects
01204     SeeAlso:    -
01205 
01206 ********************************************************************************************/
01207 
01208 BOOL BrushDefinition::SetSpacingIncrProp(double Incr)
01209 {
01210     if (Incr <= 0)
01211         return FALSE;
01212     
01213     if (Incr != 1.0)
01214     {
01215         double TenIncr = pow(Incr, 10.0);
01216         double TenthSpacing = m_BrushSpacing * TenIncr;
01217         if (TenthSpacing >= MAX_BRUSH_SPACING || TenthSpacing < MIN_BRUSH_SPACING)
01218         {
01219             ERROR3("Illegal increment value");
01220             return FALSE;
01221         }
01222     }
01223     m_BrushSpacingIncrProp = Incr;
01224     return TRUE;
01225 }
01226 
01227 
01228 
01229 /********************************************************************************************
01230 
01231 >   MILLIPOINT BrushDefinition::GetSpacingIncrProp() 
01232 
01233     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01234     Created:    6/10/99
01235     Returns:    the proportional spacing increment between the brush objects 
01236     Purpose:    As above
01237 
01238 ********************************************************************************************/
01239 
01240 double BrushDefinition::GetSpacingIncrProp()
01241 {
01242     return m_BrushSpacingIncrProp;
01243 }
01244 
01245 
01246 /********************************************************************************************
01247 
01248 >   BOOL PathProcessorBrush::SetSpacingIncrConst(MILLIPOINT Incr) 
01249 
01250     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01251     Created:    6/10/99
01252     Inputs:     the constant spacing increment value to set
01253     Returns:    TRUE if we can draw 10 objects, FALSE if the spacing is invalid 
01254     Purpose:    To set the proportional spacing increment between brush objects
01255     SeeAlso:    -
01256 
01257 ********************************************************************************************/
01258 
01259 BOOL BrushDefinition::SetSpacingIncrConst(MILLIPOINT Incr)
01260 {
01261     if (Incr <= 0)
01262         return TRUE;
01263 
01264     MILLIPOINT TenthSpacing = 10 * Incr;
01265     if (TenthSpacing >= MAX_BRUSH_SPACING || TenthSpacing < MIN_BRUSH_SPACING)
01266     {
01267         ERROR3("Illegal increment value");
01268         return FALSE;
01269     }
01270     m_BrushSpacingIncrConst = Incr;
01271     return TRUE;
01272 }
01273 
01274 
01275 /********************************************************************************************
01276 
01277 >   MILLIPOINT BrushDefinition::GetSpacingIncrConst() 
01278 
01279     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01280     Created:    6/10/99
01281     Returns:    the constant spacing increment between the brush objects 
01282     Purpose:    As above
01283 
01284 ********************************************************************************************/
01285 
01286 MILLIPOINT BrushDefinition::GetSpacingIncrConst()
01287 {
01288     return m_BrushSpacingIncrConst;
01289 }
01290 
01291 
01292 
01293 /********************************************************************************************
01294 
01295 >   UINT32 BrushDefinition::GetSpacingMaxRand() 
01296 
01297     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01298     Created:    6/10/99
01299     Returns:    the maximum percentage randomness to be applied to spacing 
01300     Purpose:    As above
01301 
01302 ********************************************************************************************/
01303 
01304 UINT32 BrushDefinition::GetSpacingMaxRand()
01305 {
01306     return m_BrushSpacingMaxRand;
01307 }
01308 
01309 
01310 /********************************************************************************************
01311 
01312 >   BOOL BrushDefinition::SetSpacingMaxRand(UINT32 Value) 
01313 
01314     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01315     Created:    6/10/99
01316     Inputs::    the maximum percentage randomness to be applied to spacing 
01317     Returns:    TRUE if Value is within the legal limits, otherwise FALSE
01318     Purpose:    As above
01319 
01320 ********************************************************************************************/
01321 
01322 BOOL BrushDefinition::SetSpacingMaxRand(UINT32 Value)
01323 {
01324     if (Value < MIN_BRUSH_RAND || Value > MAX_BRUSH_RAND)
01325         return FALSE;
01326     
01327     m_BrushSpacingMaxRand = Value;
01328     return TRUE;
01329 }
01330 
01331 
01332 /********************************************************************************************
01333 
01334 >   UINT32 BrushDefinition::GetSpacingRandSeed() 
01335 
01336     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01337     Created:    6/10/99
01338     Returns:    the seed used to determine the sequence of random numbers for spacing
01339     Purpose:    As above
01340 
01341 ********************************************************************************************/
01342 
01343 UINT32 BrushDefinition::GetSpacingRandSeed()
01344 {
01345     return m_BrushSpacingRandSeed;
01346 }
01347 
01348 
01349 /********************************************************************************************
01350 
01351 >   void BrushDefinition::SetSpacingRandSeed(UINT32 Seed) 
01352 
01353     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01354     Created:    6/10/99
01355     Inputs:     the seed to use for our spacing RNG
01356     Returns:    -
01357     Purpose:    As above
01358 
01359 ********************************************************************************************/
01360 
01361 void BrushDefinition::SetSpacingRandSeed(UINT32 Seed)
01362 {
01363     m_BrushSpacingRandSeed=Seed; // "=Seed" added by AMB 2006-01-06
01364 }
01365 
01366 /********************************************************************************************
01367 
01368 >   PathOffset BrushDefinition::GetPathOffsetType() 
01369 
01370     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01371     Created:    6/10/99
01372     Inputs:     -
01373     Returns:    The type of pathoffset this brush is using 
01374     Purpose:    as above
01375     SeeAlso:    -
01376 
01377 ********************************************************************************************/
01378 
01379 PathOffset BrushDefinition::GetPathOffsetType()
01380 {
01381     return m_PathOffsetType;
01382 }
01383 
01384 
01385 
01386 /********************************************************************************************
01387 
01388 >   void BrushDefinition::SetPathOffsetType(PathOffset Offset) 
01389 
01390     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01391     Created:    6/10/99
01392     Inputs      Offset - the offset type to set
01393     Returns:    - 
01394     Purpose:    to set the offset type for this brush
01395 ********************************************************************************************/
01396 void BrushDefinition::SetPathOffsetType(PathOffset Offset)
01397 {
01398     m_PathOffsetType = Offset;
01399 }
01400 
01401 
01402 /********************************************************************************************
01403 
01404 >   MILLIPOINT BrushDefinition::GetPathOffsetValue() 
01405 
01406     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01407     Created:    6/10/99
01408     Inputs:     -
01409     Returns:    The value of the path offset used by this brush 
01410     Purpose:    as above
01411     SeeAlso:    -
01412 
01413 ********************************************************************************************/
01414 
01415 MILLIPOINT BrushDefinition::GetPathOffsetValue()
01416 {
01417     return m_PathOffsetValue;
01418 }
01419 
01420 
01421 
01422 /********************************************************************************************
01423 
01424 >   void BrushDefinition::SetPathOffsetValue(MILLIPOINT Value) 
01425 
01426     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01427     Created:    6/10/99
01428     Inputs      Value - the offset value to set
01429     Returns:    - 
01430     Purpose:    to set the offset distance for this brush
01431 ********************************************************************************************/
01432 void BrushDefinition::SetPathOffsetValue(MILLIPOINT Value)
01433 {
01434     m_PathOffsetValue = Value;
01435 }
01436 
01437 
01438 /********************************************************************************************
01439 
01440 >   MILLIPOINT BrushDefinition::GetPathOffsetIncrConst() 
01441 
01442     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01443     Created:    6/10/99
01444     Inputs:     -
01445     Returns:    The value of the constant path offset increment used by this brush 
01446     Purpose:    as above
01447     SeeAlso:    -
01448 
01449 ********************************************************************************************/
01450 
01451 MILLIPOINT BrushDefinition::GetPathOffsetIncrConst()
01452 {
01453     return m_PathOffsetIncrConst;
01454 }
01455 
01456 
01457 
01458 /********************************************************************************************
01459 
01460 >   BOOL BrushDefinition::SetPathOffsetIncrConst(MILLIPOINT Value) 
01461 
01462     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01463     Created:    6/10/99
01464     Inputs      Value - the offset increment value to set
01465     Returns:    - 
01466     Purpose:    to set the offset distance for this brush
01467 ********************************************************************************************/
01468 
01469 BOOL BrushDefinition::SetPathOffsetIncrConst(MILLIPOINT Value)
01470 {
01471     if (Value < 0 || Value > MAX_BRUSH_SPACING)
01472         return FALSE;
01473 
01474     m_PathOffsetIncrConst = Value;
01475     return TRUE;
01476 }
01477 
01478 
01479 /********************************************************************************************
01480 
01481 >   double BrushDefinition::GetPathOffsetIncrProp() 
01482 
01483     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01484     Created:    6/10/99
01485     Inputs:     -
01486     Returns:    The value of the proportional path offset increment used by this brush 
01487     Purpose:    as above
01488     SeeAlso:    -
01489 
01490 ********************************************************************************************/
01491 
01492 double BrushDefinition::GetPathOffsetIncrProp()
01493 {
01494     return m_PathOffsetIncrProp;
01495 }
01496 
01497 
01498 
01499 /********************************************************************************************
01500 
01501 >   BOOL BrushDefinition::SetPathOffsetIncrProp(double Incr) 
01502 
01503     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01504     Created:    6/10/99
01505     Inputs      incr - the proportional offset increment value to set
01506     Returns:    - 
01507     Purpose:    to set the offset distance for this brush
01508 ********************************************************************************************/
01509 
01510 BOOL BrushDefinition::SetPathOffsetIncrProp(double Incr)
01511 {
01512     if (Incr < 0 )
01513         return FALSE;
01514     // test to see if 10 objects takes us to the limit
01515     double TenIncr = pow(Incr, 10.0);
01516     if ((m_PathOffsetValue * TenIncr) >= MAX_BRUSH_SPACING)
01517         return FALSE;
01518 
01519     m_PathOffsetIncrProp = Incr;
01520     return TRUE;
01521 }
01522 
01523 
01524 /********************************************************************************************
01525 
01526 >   UINT32 BrushDefinition::GetOffsetValueMaxRand() 
01527 
01528     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01529     Created:    6/10/99
01530     Returns:    the maximum percentage randomness to be applied to Offset
01531     Purpose:    As above
01532 
01533 ********************************************************************************************/
01534 
01535 UINT32 BrushDefinition::GetOffsetValueMaxRand()
01536 {
01537     return m_OffsetValueMaxRand;
01538 }
01539 
01540 
01541 /********************************************************************************************
01542 
01543 >   BOOL BrushDefinition::SetOffsetValueMaxRand(UINT32 Value) 
01544 
01545     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01546     Created:    6/10/99
01547     Inputs::    the maximum percentage randomness to be applied to Offset
01548     Returns:    TRUE if Value is within the legal limits, otherwise FALSE
01549     Purpose:    As above
01550 
01551 ********************************************************************************************/
01552 
01553 BOOL BrushDefinition::SetOffsetValueMaxRand(UINT32 Value)
01554 {
01555     if (Value < MIN_BRUSH_RAND || Value > MAX_BRUSH_RAND)
01556         return FALSE;
01557     
01558     m_OffsetValueMaxRand = Value;
01559     return TRUE;
01560 }
01561 
01562 
01563 /********************************************************************************************
01564 
01565 >   UINT32 BrushDefinition::GetOffsetValueRandSeed() 
01566 
01567     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01568     Created:    6/10/99
01569     Returns:    the seed used to determine the sequence of random numbers for offset value
01570     Purpose:    As above
01571 
01572 ********************************************************************************************/
01573 
01574 UINT32 BrushDefinition::GetOffsetValueRandSeed()
01575 {
01576     return m_OffsetValueRandSeed;
01577 }
01578 
01579 
01580 /********************************************************************************************
01581 
01582 >   BOOL BrushDefinition::SetOffsetValueRandSeed(UINT32 Value) 
01583 
01584     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01585     Created:    6/10/9
01586     Inputs  :   the seed used to determine the sequence of random numbers for offset value
01587     Returns:    TRUE if Value is valid, which it always is at the moment
01588     Purpose:    As above
01589                 
01590 ********************************************************************************************/
01591 
01592 void BrushDefinition::SetOffsetValueRandSeed(UINT32 Value)
01593 {
01594     m_OffsetValueRandSeed = Value;
01595     
01596 }
01597 
01598 
01599 /********************************************************************************************
01600 
01601 >   UINT32 BrushDefinition::GetOffsetTypeRandSeed() 
01602 
01603     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01604     Created:    6/10/99
01605     Returns:    the seed used to determine the sequence of random numbers for offset value
01606     Purpose:    As above
01607 
01608 ********************************************************************************************/
01609 
01610 UINT32 BrushDefinition::GetOffsetTypeRandSeed()
01611 {
01612     return m_OffsetTypeRandSeed;
01613 }
01614 
01615 
01616 /********************************************************************************************
01617 
01618 >   BOOL BrushDefinition::SetOffsetTypeRandSeed(UINT32 Value) 
01619 
01620     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01621     Created:    6/10/9
01622     Inputs  :   the seed used to determine the sequence of random numbers for offset value
01623     Returns:    TRUE if Value is valid, which it always is at the moment
01624     Purpose:    As above
01625                 
01626 ********************************************************************************************/
01627 
01628 void BrushDefinition::SetOffsetTypeRandSeed(UINT32 Value)
01629 {
01630     m_OffsetValueRandSeed = Value;
01631 
01632 }
01633 
01634 
01635 /********************************************************************************************
01636 
01637 >   void BrushDefinition::SetTiling(BOOL Value) 
01638 
01639     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01640     Created:    6/10/99
01641     Inputs:     whether or not the brush tiles
01642     Returns:    -
01643     Purpose:    as above
01644     SeeAlso:    -
01645 
01646 ********************************************************************************************/
01647 
01648 void BrushDefinition::SetTiling(BOOL Value)
01649 {
01650     m_bTile = Value;
01651 }
01652 
01653 
01654 
01655 /********************************************************************************************
01656 
01657 >   BOOL BrushDefinition::GetTiling() 
01658 
01659     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01660     Created:    6/10/99
01661     Inputs:     
01662     Returns:    whether or not the brush tiles
01663     Purpose:    as above
01664     SeeAlso:    -
01665 
01666 ********************************************************************************************/
01667 
01668 BOOL BrushDefinition::IsTiled()
01669 {
01670     return m_bTile;
01671 }
01672 
01673 
01674 
01675 /********************************************************************************************
01676 
01677 >   BOOL BrushDefinition::SetRotationAngle(double Angle) 
01678 
01679     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01680     Created:    6/10/99
01681     Inputs:     the angle of rotation to set
01682     Returns:    TRUE if the angle is within the stated bounds
01683     Purpose:    as above
01684     SeeAlso:    -
01685 
01686 ********************************************************************************************/
01687 
01688 BOOL BrushDefinition::SetRotationAngle(double Angle)
01689 {
01690 /*  if ((Angle <= MIN_ANGLE) || (Angle >= MAX_ANGLE))
01691     {
01692         ERROR3("Invalid angle");
01693         return FALSE;
01694         
01695     }*/
01696     m_RotateAngle = Angle;
01697     return TRUE;
01698 }
01699 
01700 /********************************************************************************************
01701 
01702 >   double BrushDefinition::GetRotationAngle() 
01703 
01704     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01705     Created:    6/10/99
01706     Inputs:     -
01707     Returns:    the angle of rotation that has been set
01708     Purpose:    as above
01709     SeeAlso:    -
01710 
01711 ********************************************************************************************/
01712 
01713 double BrushDefinition::GetRotationAngle()
01714 {
01715     return m_RotateAngle;
01716 }
01717 
01718 
01719 /********************************************************************************************
01720 
01721 >   BOOL BrushDefinition::SetRotAngleIncrConst(double Angle) 
01722 
01723     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01724     Created:    6/10/99
01725     Inputs:     the incremental angle of rotation to set
01726     Returns:    TRUE if the angle is within the stated bounds
01727     Purpose:    as above
01728     SeeAlso:    -
01729 
01730 ********************************************************************************************/
01731 
01732 BOOL BrushDefinition::SetRotationIncrConst(double Angle)
01733 {
01734     m_RotAngleIncrConst = Angle;
01735 
01736     return TRUE;
01737 }
01738 
01739 /********************************************************************************************
01740 
01741 >   double BrushDefinition::GetRotAngleIncrConst() 
01742 
01743     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01744     Created:    6/10/99
01745     Inputs:     -
01746     Returns:    the increment to the angle of rotation 
01747     Purpose:    as above
01748     SeeAlso:    -
01749 
01750 ********************************************************************************************/
01751 
01752 double BrushDefinition::GetRotationIncrConst()
01753 {
01754     return m_RotAngleIncrConst;
01755 }
01756 
01757 
01758 /********************************************************************************************
01759 
01760 >   BOOL BrushDefinition::SetRotAngleIncrProp(double Angle) 
01761 
01762     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01763     Created:    6/10/99
01764     Inputs:     the incremental angle of rotation to set
01765     Returns:    TRUE if the angle is within the stated bounds
01766     Purpose:    as above
01767     SeeAlso:    -
01768 
01769 ********************************************************************************************/
01770 
01771 BOOL BrushDefinition::SetRotationIncrProp(double Value)
01772 {
01773     m_RotAngleIncrProp = Value;
01774 
01775     return TRUE;
01776 }
01777 
01778 /********************************************************************************************
01779 
01780 >   double BrushDefinition::GetRotAngleIncrProp() 
01781 
01782     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01783     Created:    6/10/99
01784     Inputs:     -
01785     Returns:    the increment to the angle of rotation 
01786     Purpose:    as above
01787     SeeAlso:    -
01788 
01789 ********************************************************************************************/
01790 
01791 double BrushDefinition::GetRotationIncrProp()
01792 {
01793     return m_RotAngleIncrProp;
01794 }
01795 
01796 /********************************************************************************************
01797 
01798 >   UINT32 BrushDefinition::GetRotationMaxRand() 
01799 
01800     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01801     Created:    6/10/99
01802     Inputs:     -
01803     Returns:    the maximum amount of randomness to be applied to the rotation angle
01804     Purpose:    as above
01805     SeeAlso:    -
01806 
01807 ********************************************************************************************/
01808 
01809 UINT32 BrushDefinition::GetRotationMaxRand()
01810 {
01811     return m_RotationMaxRand;
01812 }
01813 
01814 
01815 /********************************************************************************************
01816 
01817 >   BOOL BrushDefinition::SetRotationMaxRand(UINT32 Value) 
01818 
01819     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01820     Created:    6/10/99
01821     Inputs:     the maximum amount of randomness (as a %) to be applied to rotation
01822     Returns:    -
01823     Purpose:    as above
01824     SeeAlso:    -
01825 
01826 ********************************************************************************************/
01827 
01828 BOOL BrushDefinition::SetRotationMaxRand(UINT32 Value)
01829 {
01830     m_RotationMaxRand = Value;
01831     return TRUE;
01832 }
01833 
01834 
01835 /********************************************************************************************
01836 
01837 >   UINT32 BrushDefinition::GetRotationRandSeed() 
01838 
01839     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01840     Created:    6/10/99
01841     Inputs:     -
01842     Returns:    the  seed to use to generate the  rotation RNG
01843     Purpose:    as above
01844     SeeAlso:    -
01845 
01846 ********************************************************************************************/
01847 
01848 UINT32 BrushDefinition::GetRotationRandSeed()
01849 {
01850     return m_RotationRandSeed;
01851 }
01852 
01853 
01854 
01855 /********************************************************************************************
01856 
01857 >   BOOL BrushDefinition::SetRotationRandSeed(UINT32 Seed) 
01858 
01859     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01860     Created:    6/10/99
01861     Inputs:     the seed to use
01862     Returns:    -
01863     Purpose:    as above
01864     SeeAlso:    -
01865 
01866 ********************************************************************************************/
01867 
01868 void BrushDefinition::SetRotationRandSeed(UINT32 Seed)
01869 {
01870     m_RotationRandSeed = Seed;
01871 }
01872 
01873 /********************************************************************************************
01874 
01875 >   UINT32 BrushDefinition::GetRotationMaxPressure() 
01876 
01877     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01878     Created:    6/10/99
01879     Inputs:     -
01880     Returns:    the  seed to use to generate the  rotation RNG
01881     Purpose:    as above
01882     SeeAlso:    -
01883 
01884 ********************************************************************************************/
01885 
01886 UINT32 BrushDefinition::GetRotationMaxPressure()
01887 {
01888     return m_RotationMaxPressure;
01889 }
01890 
01891 
01892 
01893 /********************************************************************************************
01894 
01895 >   BOOL BrushDefinition::SetRotationMaxPressure(UINT32 Seed) 
01896 
01897     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01898     Created:    6/10/99
01899     Inputs:     the seed to use
01900     Returns:    -
01901     Purpose:    as above
01902     SeeAlso:    -
01903 
01904 ********************************************************************************************/
01905 
01906 BOOL BrushDefinition::SetRotationMaxPressure(UINT32 Value)
01907 {
01908     if (Value < MIN_PRESSURE_EFFECT || Value > MAX_PRESSURE_EFFECT)
01909         return FALSE;
01910     m_RotationMaxPressure = Value;
01911     return TRUE;
01912 }
01913 
01914 
01915 /********************************************************************************************
01916 
01917 >   BOOL BrushDefinition::IsRotated() 
01918 
01919     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01920     Created:    6/10/99
01921     Inputs:     
01922     Returns:    whether or not the brush objects are rotated
01923     Purpose:    as above
01924     SeeAlso:    -
01925 
01926 ********************************************************************************************/
01927 
01928 BOOL BrushDefinition::IsRotated()
01929 {
01930     return m_bRotate;
01931 }
01932 
01933 
01934 /********************************************************************************************
01935 
01936 >   void BrushDefinition::SetRotation(BOOL Value) 
01937 
01938     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01939     Created:    6/10/99
01940     Inputs:     whether or not the brush rotates
01941     Returns:    -
01942     Purpose:    as above
01943     SeeAlso:    -
01944 
01945 ********************************************************************************************/
01946 
01947 void BrushDefinition::SetRotated(BOOL Value)
01948 {
01949     m_bRotate = Value;
01950 }
01951 
01952 
01953 
01954 /********************************************************************************************
01955 
01956 >   bool BrushDefinition::SetScaling(double Scale) 
01957 
01958     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01959     Created:    6/10/99
01960     Inputs:     the scale factor to set
01961     Returns:    TRUE if Scale is within the permitted bounds
01962     Purpose:    to set the member that determine to what scale of the original object each 
01963                 brush object is drawn
01964     SeeAlso:    -
01965 
01966 ********************************************************************************************/
01967 
01968 BOOL BrushDefinition::SetBrushScaling(double Scale)
01969 {
01970     if (Scale <= MIN_BRUSH_SCALE || Scale >= MAX_BRUSH_SCALE)
01971         return FALSE;
01972     
01973     m_BrushScaling = Scale;
01974     return TRUE;
01975 }
01976 
01977 
01978 /********************************************************************************************
01979 
01980 >   double BrushDefinition::GetBrushScaling() 
01981 
01982     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01983     Created:    6/10/99
01984     Inputs:     -
01985     Returns:    the scaling factor to use when drawing the objects
01986     Purpose:    as above
01987     SeeAlso:    -
01988 
01989 ********************************************************************************************/
01990 
01991 double BrushDefinition::GetBrushScaling()
01992 {
01993     return m_BrushScaling;
01994 }
01995 
01996 
01997 /********************************************************************************************
01998 
01999 >   double BrushDefinition::GetBrushScalingIncr() 
02000 
02001     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02002     Created:    6/10/99
02003     Inputs:     -
02004     Returns:    the scaling factor increment to use when drawing the objects
02005     Purpose:    as above
02006     SeeAlso:    -
02007 
02008 ********************************************************************************************/
02009 
02010 double BrushDefinition::GetBrushScalingIncr()
02011 {
02012     return m_BrushScalingIncr;
02013 }
02014 
02015 
02016 
02017 /********************************************************************************************
02018 
02019 >   bool BrushDefinition::SetBrushScalingincr(double incr) 
02020 
02021     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02022     Created:    6/10/99
02023     Inputs:     the scale factor increment to set
02024     Returns:    TRUE unless incr is negative
02025     Purpose:    to set the member that determine the increment to scaling applied
02026                 to each brush object
02027                 
02028     SeeAlso:    -
02029 
02030 ********************************************************************************************/
02031 
02032 BOOL BrushDefinition::SetBrushScalingIncr(double Incr)
02033 {
02034     if (Incr <= 0)
02035     {
02036         ERROR3("Negative scaling increment");
02037         return FALSE;
02038     }
02039 
02040     m_BrushScalingIncr = Incr;
02041     return TRUE;
02042 }
02043 
02044 
02045 /********************************************************************************************
02046 
02047 >   double BrushDefinition::GetBrushScalingIncrConst() 
02048 
02049     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02050     Created:    6/10/99
02051     Inputs:     -
02052     Returns:    the scaling factor increment to use when drawing the objects
02053     Purpose:    as above
02054     SeeAlso:    -
02055 
02056 ********************************************************************************************/
02057 
02058 double BrushDefinition::GetBrushScalingIncrConst()
02059 {
02060     return m_BrushScalingIncrConst;
02061 }
02062 
02063 
02064 
02065 /********************************************************************************************
02066 
02067 >   bool BrushDefinition::SetBrushScalingincrConst(INT32 Incr) 
02068 
02069     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02070     Created:    6/10/99
02071     Inputs:     the scale factor increment to set
02072     Returns:    TRUE unless Incr >= 100
02073     Purpose:    to set the member that determine the increment to scaling applied
02074                 to each brush object
02075                 
02076     SeeAlso:    -
02077 
02078 ********************************************************************************************/
02079 
02080 BOOL BrushDefinition::SetBrushScalingIncrConst(double Incr)
02081 {
02082     if (abs((INT32)Incr) >= 100)
02083     {
02084         return FALSE;
02085     }
02086     m_BrushScalingIncrConst = Incr;
02087     return TRUE;
02088 }
02089 
02090 /********************************************************************************************
02091 
02092 >   UINT32 BrushDefinition::GetScalingMaxRand() 
02093 
02094     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02095     Created:    6/10/99
02096     Returns:    the maximum percentage randomness to be applied to Scaling 
02097     Purpose:    As above
02098 
02099 ********************************************************************************************/
02100 
02101 UINT32 BrushDefinition::GetScalingMaxRand()
02102 {
02103     return m_BrushScalingMaxRand;
02104 }
02105 
02106 
02107 /********************************************************************************************
02108 
02109 >   BOOL BrushDefinition::SetScalingMaxRand(UINT32 Value) 
02110 
02111     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02112     Created:    6/10/99
02113     Inputs::    the maximum percentage randomness to be applied to Scaling 
02114     Returns:    TRUE if Value is within the legal limits, otherwise FALSE
02115     Purpose:    As above
02116 
02117 ********************************************************************************************/
02118 
02119 BOOL BrushDefinition::SetScalingMaxRand(UINT32 Value)
02120 {
02121     if (Value < MIN_BRUSH_RAND || Value > MAX_BRUSH_RAND)
02122         return FALSE;
02123     
02124     m_BrushScalingMaxRand = Value;
02125     return TRUE;
02126 }
02127 
02128 
02129 /********************************************************************************************
02130 
02131 >   UINT32 BrushDefinition::GetScalingRandSeed() 
02132 
02133     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02134     Created:    6/10/99
02135     Returns:    the seed used to determine the sequence of random numbers for Scaling
02136     Purpose:    As above
02137 
02138 ********************************************************************************************/
02139 
02140 UINT32 BrushDefinition::GetScalingRandSeed()
02141 {
02142     return m_BrushScalingRandSeed;
02143 }
02144 
02145 
02146 /********************************************************************************************
02147 
02148 >   void BrushDefinition::SetScalingRandSeed(UINT32 Seed) 
02149 
02150     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02151     Created:    6/10/99
02152     Inputs:     the seed to use for our scaling RNG
02153     Returns:    -
02154     Purpose:    As above
02155 
02156 ********************************************************************************************/
02157 
02158 void BrushDefinition::SetScalingRandSeed(UINT32 Seed)
02159 {
02160     m_BrushScalingRandSeed = Seed;
02161 }
02162 
02163 
02164 /********************************************************************************************
02165 
02166 >   UINT32 BrushDefinition::GetScalingMaxPressure() 
02167 
02168     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02169     Created:    6/10/99
02170     Returns:    the maximum percentage effect that pressure will have on Scaling 
02171     Purpose:    As above
02172 
02173 ********************************************************************************************/
02174 
02175 UINT32 BrushDefinition::GetScalingMaxPressure()
02176 {
02177     return m_ScalingMaxPressure;
02178 }
02179 
02180 
02181 /********************************************************************************************
02182 
02183 >   BOOL BrushDefinition::SetScalingMaxPressure(UINT32 Pressure) 
02184 
02185     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02186     Created:    6/10/99
02187     Inputs:     the maximum percentage effect that pressure will have on Scaling 
02188     Returns:    -
02189     Purpose:    As above
02190 
02191 ********************************************************************************************/
02192 
02193 BOOL BrushDefinition::SetScalingMaxPressure(UINT32 Max)
02194 {
02195     if (Max < MIN_PRESSURE_EFFECT || Max > MAX_PRESSURE_EFFECT)
02196         return FALSE;
02197     m_ScalingMaxPressure = Max;
02198     return TRUE;
02199 }
02200 
02201 
02202 
02203 /********************************************************************************************
02204 
02205 >   double BrushDefinition::GetHueIncrement()
02206 
02207     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02208     Created:    6/10/99
02209     Inputs:     -
02210     Returns:    the hue increment for this brush
02211     Purpose:    as above
02212     SeeAlso:    -
02213 
02214 ********************************************************************************************/
02215 
02216 double BrushDefinition::GetHueIncrement()
02217 {
02218     return m_BrushHueIncrement;
02219 }
02220 
02221 
02222 /********************************************************************************************
02223 
02224 >   double BrushDefinition::GetHueIncrement()
02225 
02226     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02227     Created:    6/10/99
02228     Inputs:     the hue increment for this brush
02229     Returns:    -
02230     Purpose:    as above
02231     SeeAlso:    -
02232 
02233 ********************************************************************************************/
02234 
02235 BOOL BrushDefinition::SetHueIncrement(double Incr)
02236 {
02237     m_BrushHueIncrement = Incr;
02238     return TRUE;
02239 }
02240 
02241 
02242 /********************************************************************************************
02243 
02244 >   UINT32 BrushDefinition::GetHueMaxRand()
02245 
02246     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02247     Created:    6/10/99
02248     Inputs:     -
02249     Returns:    the hue increment random amount for this brush
02250     Purpose:    as above
02251     SeeAlso:    -
02252 
02253 ********************************************************************************************/
02254 
02255 UINT32 BrushDefinition::GetHueMaxRand()
02256 {
02257     return m_BrushHueMaxRand;
02258 }
02259 
02260 
02261 
02262 /********************************************************************************************
02263 
02264 >   BOOL BrushDefinition::SetHueMaxRand(UINT32 Rand)
02265 
02266     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02267     Created:    6/10/99
02268     Inputs:     the hue increment random amount for this brush
02269     Returns:    -
02270     Purpose:    as above
02271     SeeAlso:    -
02272 
02273 ********************************************************************************************/
02274 
02275 BOOL BrushDefinition::SetHueMaxRand(UINT32 Rand)
02276 {
02277     m_BrushHueMaxRand = Rand;
02278     return TRUE;
02279 }
02280 
02281 
02282 /********************************************************************************************
02283 
02284 >   UINT32 BrushDefinition::GetHueRandSeed()
02285 
02286     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02287     Created:    6/10/99
02288     Inputs:     -
02289     Returns:    the hue increment random amount for this brush
02290     Purpose:    as above
02291     SeeAlso:    -
02292 
02293 ********************************************************************************************/
02294 
02295 UINT32 BrushDefinition::GetHueRandSeed()
02296 {
02297     return m_BrushHueRandSeed;
02298 }
02299 
02300 
02301 
02302 /********************************************************************************************
02303 
02304 >   BOOL BrushDefinition::SetHueRandSeed(UINT32 Rand)
02305 
02306     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02307     Created:    6/10/99
02308     Inputs:     the hue increment random amount for this brush
02309     Returns:    -
02310     Purpose:    as above
02311     SeeAlso:    -
02312 
02313 ********************************************************************************************/
02314 
02315 BOOL BrushDefinition::SetHueRandSeed(UINT32 Rand)
02316 {
02317     m_BrushHueRandSeed = Rand;
02318     return TRUE;
02319 }
02320 
02321 
02322 /********************************************************************************************
02323 
02324 >   double BrushDefinition::GetSatIncrement()
02325 
02326     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02327     Created:    6/10/99
02328     Inputs:     -
02329     Returns:    the Saturation increment for this brush
02330     Purpose:    as above
02331     SeeAlso:    -
02332 
02333 ********************************************************************************************/
02334 
02335 double BrushDefinition::GetSatIncrement()
02336 {
02337     return m_BrushSatIncrement;
02338 }
02339 
02340 
02341 /********************************************************************************************
02342 
02343 >   double BrushDefinition::GetSatIncrement()
02344 
02345     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02346     Created:    6/10/99
02347     Inputs:     the Saturation increment for this brush
02348     Returns:    -
02349     Purpose:    as above
02350     SeeAlso:    -
02351 
02352 ********************************************************************************************/
02353 
02354 BOOL BrushDefinition::SetSatIncrement(double Incr)
02355 {
02356     m_BrushSatIncrement = Incr;
02357     return TRUE;
02358 }
02359 
02360 
02361 /********************************************************************************************
02362 
02363 >   UINT32 BrushDefinition::GetSatMaxRand()
02364 
02365     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02366     Created:    6/10/99
02367     Inputs:     -
02368     Returns:    the Saturation increment random amount for this brush
02369     Purpose:    as above
02370     SeeAlso:    -
02371 
02372 ********************************************************************************************/
02373 
02374 UINT32 BrushDefinition::GetSatMaxRand()
02375 {
02376     return m_BrushSatMaxRand;
02377 }
02378 
02379 
02380 
02381 /********************************************************************************************
02382 
02383 >   BOOL BrushDefinition::SetSatMaxRand(UINT32 Rand)
02384 
02385     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02386     Created:    6/10/99
02387     Inputs:     the Saturation increment random amount for this brush
02388     Returns:    -
02389     Purpose:    as above
02390     SeeAlso:    -
02391 
02392 ********************************************************************************************/
02393 
02394 BOOL BrushDefinition::SetSatMaxRand(UINT32 Rand)
02395 {
02396     m_BrushSatMaxRand = Rand;
02397     return TRUE;
02398 }
02399 
02400 
02401 /********************************************************************************************
02402 
02403 >   UINT32 BrushDefinition::GetSatRandSeed()
02404 
02405     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02406     Created:    6/10/99
02407     Inputs:     -
02408     Returns:    the Saturation increment random amount for this brush
02409     Purpose:    as above
02410     SeeAlso:    -
02411 
02412 ********************************************************************************************/
02413 
02414 UINT32 BrushDefinition::GetSatRandSeed()
02415 {
02416     return m_BrushSatRandSeed;
02417 }
02418 
02419 
02420 
02421 /********************************************************************************************
02422 
02423 >   BOOL BrushDefinition::SetSatRandSeed(UINT32 Rand)
02424 
02425     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02426     Created:    6/10/99
02427     Inputs:     the Saturation increment random amount for this brush
02428     Returns:    -
02429     Purpose:    as above
02430     SeeAlso:    -
02431 
02432 ********************************************************************************************/
02433 
02434 BOOL BrushDefinition::SetSatRandSeed(UINT32 Rand)
02435 {
02436     m_BrushSatRandSeed = Rand;
02437     return TRUE;
02438 }
02439 
02440 
02441 
02442 /********************************************************************************************
02443 
02444 >   INT32 BrushDefinition::GetBrushTransparency()
02445 
02446     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02447     Created:    6/10/99
02448     Inputs:     Value - the value to set
02449     Returns:    our transparency value 
02450     Purpose:    as above
02451     SeeAlso:    -
02452 
02453 ********************************************************************************************/
02454 
02455 INT32 BrushDefinition::GetBrushTransparency()
02456 {
02457     return m_BrushTransparency;
02458 }
02459 
02460 /********************************************************************************************
02461 
02462 >   BOOL BrushDefinition::SetBrushTransparency(INT32 Value)
02463 
02464     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02465     Created:    6/10/99
02466     Inputs:     Value - the value to set
02467     Returns:    our transparency value (-1 indicates unused)
02468     Purpose:    as above
02469     SeeAlso:    -
02470 
02471 ********************************************************************************************/
02472 
02473 BOOL BrushDefinition::SetBrushTransparency(INT32 Value)
02474 {
02475     if (Value > MAX_TRANSP_VALUE)
02476         return FALSE;
02477 
02478     m_BrushTransparency = Value;
02479     return TRUE;
02480 }
02481 
02482 
02483 /********************************************************************************************
02484 
02485 >   BOOL BrushDefinition::SetTransparencyPressure(UINT32 Value)
02486 
02487     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02488     Created:    6/10/99
02489     Inputs:     Value - the value to set
02490     Returns:    
02491     Purpose:    Sets the extent to which pressure affects transparency
02492     SeeAlso:    -
02493 
02494 ********************************************************************************************/
02495 
02496 BOOL BrushDefinition::SetTransparencyPressure(UINT32 Value)
02497 {
02498     m_TranspMaxPressure = Value;
02499     return TRUE;
02500 }
02501 
02502 
02503 /********************************************************************************************
02504 
02505 >   BOOL BrushDefinition::GetTransparencyPressure(UINT32 Value)
02506 
02507     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02508     Created:    6/10/99
02509     Inputs:     Value - the value to set
02510     Returns:    
02511     Purpose:    Sets the extent to which pressure affects transparency
02512     SeeAlso:    -
02513 
02514 ********************************************************************************************/
02515 
02516 UINT32 BrushDefinition::GetTransparencyPressure()
02517 {
02518     return m_TranspMaxPressure;
02519 }
02520 
02521 
02522 /********************************************************************************************
02523 
02524 >   SequenceType BrushDefinition::GetSequenceType() 
02525 
02526     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02527     Created:    6/10/99
02528     Inputs:     -
02529     Returns:    the type of sequence we are using for mutliple ink objects
02530     Purpose:    as above
02531     SeeAlso:    -
02532 
02533 ********************************************************************************************/
02534 
02535 SequenceType BrushDefinition::GetSequenceType()
02536 {
02537     return m_SequenceType;
02538 }
02539 
02540 
02541 /********************************************************************************************
02542 
02543 >   void BrushDefinition::SetSequenceType(SequenceType Type) 
02544 
02545     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02546     Created:    6/10/99
02547     Inputs:     the type of sequence to use
02548     Returns:    -
02549     Purpose:    as above
02550     SeeAlso:    -
02551 
02552 ********************************************************************************************/
02553 
02554 void BrushDefinition::SetSequenceType(SequenceType Type)
02555 {
02556     m_SequenceType = Type;
02557 }
02558 
02559 
02560 /********************************************************************************************
02561 
02562 >   void BrushDefinition::SetSequenceSeed(UINT32 Seed) 
02563 
02564     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02565     Created:    6/10/99
02566     Inputs:     the random seed to use for sequences
02567     Returns:    -
02568     Purpose:    as above
02569     SeeAlso:    -
02570 
02571 ********************************************************************************************/
02572 
02573 void BrushDefinition::SetSequenceSeed(UINT32 Seed)
02574 {
02575     m_SequenceRandSeed = Seed;
02576 }
02577 
02578 
02579 /********************************************************************************************
02580 
02581 >   UINT32 BrushDefinition::GetSequenceSeed) 
02582 
02583     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02584     Created:    6/10/99
02585     Inputs:     -
02586     Returns:    the seed we are using to generate random sequences
02587     Purpose:    as above
02588     SeeAlso:    -
02589 
02590 ********************************************************************************************/
02591 
02592 UINT32 BrushDefinition::GetSequenceSeed()
02593 {
02594     return m_SequenceRandSeed;
02595 }
02596 
02597 /********************************************************************************************
02598 
02599 >   UINT32 BrushDefinition::GetNumBrushObjects() 
02600 
02601     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02602     Created:    6/10/99
02603     Inputs:     -
02604     Returns:    the number of brush objects used by this brush
02605     Purpose:    as above
02606     SeeAlso:    -
02607 
02608 ********************************************************************************************/
02609 
02610 UINT32 BrushDefinition::GetNumBrushObjects() const
02611 {
02612     return m_NumBrushObjects;
02613 }
02614 
02615 
02616 /********************************************************************************************
02617 
02618 >   UINT32 BrushDefinition::GetBrushFileID() 
02619 
02620     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02621     Created:    6/10/99
02622     Inputs:     -
02623     Returns:    the ID of the default file that this brush was created from (if there is one)
02624     Purpose:    as above
02625     SeeAlso:    -
02626 
02627 ********************************************************************************************/
02628 
02629 UINT32 BrushDefinition::GetBrushFileID()
02630 {
02631     return m_DefaultFileID;
02632 }
02633 
02634 /********************************************************************************************
02635 
02636 >   void BrushDefinition::SetBrushFileID(UINT32 ID)
02637 
02638     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02639     Created:    6/10/99
02640     Inputs:     ID - the ID of the default file that this file is being created from
02641     Returns:    -
02642     Purpose:    as above, this should only be called as part of the start-up process.
02643 ********************************************************************************************/
02644 
02645 void BrushDefinition::SetBrushFileID(UINT32 ID)
02646 {
02647     m_DefaultFileID = ID;
02648 }
02649 
02650 /********************************************************************************************
02651 
02652 >   BrushRef* BrushDefinition::GetFirstBrushRef() 
02653 
02654     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02655     Created:    6/10/99
02656     Inputs:     -
02657     Returns:    the first in the brushref array
02658     Purpose:    as above
02659     SeeAlso:    -
02660 
02661 ********************************************************************************************/
02662 
02663 BrushRef* BrushDefinition::GetFirstBrushRef()
02664 {
02665     if( m_BrushRefPtrArray.empty() )
02666     {
02667         ERROR3("The array is empty!");
02668         return NULL;
02669     }
02670     m_LastBrushRefRetrieved = 0;
02671     return m_BrushRefPtrArray[0];
02672 }
02673 
02674 
02675 
02676 /********************************************************************************************
02677 
02678 >   BrushRef* BrushDefinition::GetNextBrushRef() 
02679 
02680     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02681     Created:    6/10/99
02682     Inputs:     -
02683     Returns:    the next element in the brushref array, as kept track of by 
02684                 m_LastBrushRefRetrieved
02685     Purpose:    as above
02686     SeeAlso:    -
02687 
02688 ********************************************************************************************/
02689 
02690 BrushRef* BrushDefinition::GetNextBrushRef()
02691 {
02692     // have we hit the end?
02693     if( m_LastBrushRefRetrieved >= m_NumBrushObjects - 1 )
02694         return NULL;
02695 
02696     // quick check so we don't violate
02697     if( m_LastBrushRefRetrieved >= (UINT32)m_BrushRefPtrArray.size() - 1 )
02698     {
02699         ERROR3("Overran the array");
02700         return NULL;
02701     }
02702     return m_BrushRefPtrArray[++m_LastBrushRefRetrieved];
02703 }
02704 
02705 
02706 /********************************************************************************************
02707 0
02708 >   BrushRef* BrushDefinition::GetBrushRef(UINT32 Index) 
02709 
02710     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02711     Created:    6/10/99
02712     Inputs:     Index - the array element to get
02713     Returns:    the brushref at position Index in the array, or NULL if the index is invalid
02714     Purpose:    as above
02715     SeeAlso:    -
02716 
02717 ********************************************************************************************/
02718 
02719 BrushRef* BrushDefinition::GetBrushRef(UINT32 Index)
02720 {
02721     // check that the index is ok
02722     if( Index > m_NumBrushObjects || Index > (UINT32)( m_BrushRefPtrArray.size() - 1 ) )
02723     {
02724         ERROR3("Invalid index");
02725         return NULL;
02726     }
02727 
02728     // update our member
02729     m_LastBrushRefRetrieved = Index;
02730     return m_BrushRefPtrArray[Index];
02731 }
02732 
02733 
02734 /********************************************************************************************
02735 
02736 >   BOOL BrushDefinition::BrushContainsGroup() 
02737 
02738     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02739     Created:    6/10/99
02740     Inputs:     -
02741     Returns:    TRUE, if the brush is made from one or more groups, FALSE if not
02742     Purpose:    as above
02743     SeeAlso:    -
02744 
02745 ********************************************************************************************/
02746 
02747 BOOL BrushDefinition::BrushContainsGroup()
02748 {
02749     for (UINT32 i = 0; i < m_NumBrushObjects; i++)
02750     {
02751         if (m_BrushRefPtrArray[i]->GetNumBlendPaths() > 1)
02752             return TRUE;
02753     }
02754     return FALSE;
02755 }
02756 
02757 /********************************************************************************************
02758 
02759 >   DocRect BrushDefinition::GetLargestBoundingBox() 
02760 
02761     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02762     Created:    6/10/99
02763     Inputs:     -
02764     Returns:    the largest bounding box of all the objects in this definition
02765     Purpose:    as above
02766     SeeAlso:    -
02767 
02768 ********************************************************************************************/
02769 
02770 DocRect BrushDefinition::GetLargestBoundingBox()
02771 {
02772     // if the member is not empty then we have done this search so return it now
02773     if (!m_LargestBoundingBox.IsEmpty())
02774         return m_LargestBoundingBox;
02775 
02776     // otherwise search through the brushrefs
02777     BrushRef* pBrushRef = GetFirstBrushRef();
02778     DocRect   BRect;
02779     DocRect   BiggestRect;
02780     XLONG     BiggestArea = 0;
02781     while (pBrushRef != NULL)
02782     {   
02783         BRect = pBrushRef->GetBoundingRect();
02784         XLONG RectHeight = BRect.Height();
02785         XLONG RectWidth = BRect.Width();
02786         XLONG ThisRectArea = RectHeight * RectWidth;
02787         
02788         if (ThisRectArea > BiggestArea)
02789         {
02790             BiggestRect = BRect;
02791             BiggestArea = ThisRectArea;
02792             
02793         }
02794         pBrushRef = GetNextBrushRef();
02795 
02796     }
02797     m_LargestBoundingBox = BiggestRect;
02798     return BiggestRect;
02799 }
02800 
02801 
02802 
02803 /********************************************************************************************
02804 
02805 >   DocRect BrushDefinition::GetLargestPossibleRect(BOOL AdjustForLineWidth = FALSE)
02806 
02807     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02808     Created:    6/10/99
02809     Inputs:     AdjustForLineWidth - do we include scaling to the current line width in our
02810                 calculations?
02811     Returns:    the largest bounding box of all the objects in this definition, plus adjustments
02812                 for variations in scale
02813     
02814     Purpose:    To find out the largest possible bounding box that this brush can achieve, this we
02815                 get the largest ink rect and then perform the maximum scaling, rotation etc.
02816                 Note that ScalingIncrConst will be will be excluded from this test as we will
02817                 never be able to know what affect it will have in advance of drawing the path.
02818 
02819     Note:       Only use this function to determine the size of the bounding box, the location
02820                 information should not be used.
02821     SeeAlso:    -
02822 
02823 ********************************************************************************************/
02824 
02825 DocRect BrushDefinition::GetLargestPossibleRect(BOOL AdjustForLineWidth)
02826 {
02827     DocRect BRect = GetLargestBoundingBox();
02828     
02829     if (BRect.IsEmpty())  // just quit now
02830         return BRect;
02831     
02832     double Scale = 1.0;
02833 
02834     MILLIPOINT LineWidth = GetDefaultLineWidth(TRUE);
02835     
02836     // if we are including the scale to linewidth then work that out here
02837     if (AdjustForLineWidth)
02838     {
02839         MILLIPOINT CurrentLineWidth = OpDrawBrush::GetCurrentLineWidthIfNotDefault();
02840         if (CurrentLineWidth != -1 && CurrentLineWidth > 501) // -1 indicates the default linewidth, hence no scaling
02841         {
02842             Scale = (double)CurrentLineWidth / (double)LineWidth;
02843             // otherwise use the current line width
02844             LineWidth = CurrentLineWidth;
02845         }
02846     }
02847     
02848     // increase the size if we have randomness or pressure
02849     UINT32 MaxRand = GetScalingMaxRand();
02850     double dRand = ((double)MaxRand * 0.01) + 1.0;
02851     UINT32 MaxPressure = GetScalingMaxPressure();
02852     double dPressure = ((double)MaxPressure * 0.01) + 1.0;
02853     
02854     Scale *= dRand;
02855     Scale *= dPressure;
02856 
02857     if (Scale != 1.0)
02858     {
02859         double Height = (double)BRect.Height() * Scale;
02860         double Width = (double)BRect.Width() * Scale;
02861 
02862         BRect.lo.x = 0;
02863         BRect.hi.x = (MILLIPOINT)Height;
02864         BRect.lo.y = 0;
02865         BRect.hi.y = (MILLIPOINT)Width;
02866     }
02867 //  DocRect BRect(0, 0, LineWidth* 1.1, LineWidth* 1.1);
02868 
02869     // as the shape might get rotated we make sure the bitmap is big enough to cope
02870     // so make a temporary rect, rotate it and expand it, and union it with the original
02871     if (m_bRotate || m_RotateAngle || m_RotAngleIncrConst || m_RotationMaxRand)
02872     {
02873         DocRect TempRect = BRect;
02874         BrushAttrValue::RotateBounds(90, &TempRect);
02875         BRect = BRect.Union(TempRect);
02876         TempRect = BRect;
02877         BrushAttrValue::RotateBounds(45, &TempRect);
02878         BRect = BRect.Union(TempRect);
02879     }
02880     
02881     
02882     return BRect;
02883 }
02884 
02885 /********************************************************************************************
02886 
02887 >   double BrushDefinition::GetTimeStampingPeriod() 
02888 
02889     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02890     Created:    6/10/99
02891     Inputs:     -
02892     Returns:    the time stamping period for this brush, if zero then timestamping is disabled
02893     Purpose:    as above
02894     SeeAlso:    -
02895 
02896 ********************************************************************************************/
02897 
02898 double BrushDefinition::GetTimeStampingPeriod()
02899 {
02900     return m_TimeStampPeriod;
02901 }
02902 
02903 
02904 
02905 /********************************************************************************************
02906 
02907 >   BOOL BrushDefinition::SetTimeStampingPeriod(double Period) 
02908 
02909     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02910     Created:    6/10/99
02911     Inputs:     time period to set
02912     Returns:    TRUE if period is valid, else FALSE
02913     Purpose:    as above
02914     SeeAlso:    -
02915 
02916 ********************************************************************************************/
02917 
02918 BOOL BrushDefinition::SetTimeStampingPeriod(double Period)
02919 {
02920     if (Period < MIN_TIMESTAMP || Period > MAX_TIMESTAMP)
02921         return FALSE;
02922 
02923     m_TimeStampPeriod = Period;
02924     return TRUE;
02925 }
02926 
02927 /********************************************************************************************
02928 
02929 >   MILLIPOINT BrushDefinition::GetDefaultLineWidth() 
02930 
02931     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02932     Created:    6/10/99
02933     Inputs:     -
02934     Returns:    the height of the largest bounding box, to be used as a default line width
02935     Purpose:    as above
02936     SeeAlso:    -
02937 
02938 ********************************************************************************************/
02939 
02940 MILLIPOINT BrushDefinition::GetDefaultLineWidth(BOOL IgnorePressure)
02941 {
02942     DocRect BRect = GetLargestBoundingBox();
02943     MILLIPOINT Height = BRect.Height();
02944     MILLIPOINT Width = BRect.Width();
02945 //  double dHeight = (double)Height;
02946 //  double dWidth = (double)Width;
02947 
02948     double ScaleFactor = 1.0;
02949 
02950     // firstly, if we are rotated, or have random rotation, then use the longest side
02951 //  if (m_RotationMaxRand > 0 || m_RotateAngle != 0.0 || !m_bRotate)
02952     {
02953         if (Width > Height)
02954             Height = Width;
02955     }
02956     
02957     
02958     // next increase by our maximum possible random scaling
02959     if (m_BrushScalingMaxRand > 0)
02960     {
02961         // find out the random range
02962         UINT32 Lower = 0;
02963         UINT32 Upper = 0;
02964         PathProcessorBrush::GetRandomLimits(100, m_BrushScalingMaxRand, &Lower, &Upper);
02965         
02966         //Use the upper limit
02967         ScaleFactor *= ((double)Upper * 0.01);
02968     }
02969 
02970     // and our maximum possible pressure effect
02971 /*  if (m_ScalingMaxPressure > 0 && !IgnorePressure)
02972     {
02973         ScaleFactor *= ((double)m_ScalingMaxPressure * 0.01 + 1);
02974         
02975     }
02976 */
02977 
02978     MILLIPOINT NewHeight = (MILLIPOINT)((double)Height * ScaleFactor);
02979 
02980     // if we have random offset then there will be some effect, this is separate from the offset amount
02981     if (m_OffsetValueMaxRand > 0)
02982     {
02983         // rand value is a percentage of object size
02984         double RandMultiplier = (double)m_OffsetValueMaxRand * 0.01;
02985         double OffsetAmount = (double)Height * RandMultiplier;
02986         
02987         // remember that it goes both sides
02988         MILLIPOINT mpAmount = (MILLIPOINT)(2*OffsetAmount);
02989         NewHeight += mpAmount;
02990     }
02991 
02992     // if we are offset then add that amount
02993     switch (m_PathOffsetType)
02994     {
02995         case OFFSET_NONE:
02996             break;
02997         case OFFSET_LEFT:
02998         case OFFSET_RIGHT:
02999         case OFFSET_ALTERNATE:
03000         {
03001             MILLIPOINT OffsetIncr = 2 * m_PathOffsetValue;
03002             NewHeight += OffsetIncr;
03003         }
03004         break;
03005         case OFFSET_RANDOM:
03006             break;
03007         default:
03008             ERROR3("Invalid offset type");
03009     }
03010 
03011     return NewHeight;
03012 }
03013 
03014 
03015 
03016 /********************************************************************************************
03017 
03018 >   void BrushDefinition::InitialiseBrushData() 
03019 
03020     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03021     Created:    6/10/99
03022     Inputs:     -
03023     Returns:    -
03024     Purpose:    retrieves data from the path processor and puts it into our brushdata object
03025     SeeAlso:    -
03026 
03027 ********************************************************************************************/
03028 
03029 void BrushDefinition::InitialiseBrushData(BrushData* pData)
03030 {
03031     pData->m_BrushHandle = 100;
03032     
03033     pData->m_BrushScaling = m_BrushScaling;
03034     pData->m_BrushScalingIncr = m_BrushScalingIncr;
03035     pData->m_BrushScalingMaxRand = m_BrushScalingMaxRand;
03036     pData->m_BrushScalingRandSeed = m_BrushScalingRandSeed;
03037     pData->m_ScalingMaxPressure = m_ScalingMaxPressure;
03038 
03039     pData->m_bRotate = m_bRotate;
03040     pData->m_RotateAngle = m_RotateAngle;
03041     pData->m_RotAngleIncrConst = m_RotAngleIncrConst;
03042     pData->m_RotAngleIncrProp  = m_RotAngleIncrProp;
03043     pData->m_RotationMaxRand = m_RotationMaxRand;
03044     pData->m_RotationRandSeed = m_RotationRandSeed;
03045 
03046     pData->m_BrushSpacing  = m_BrushSpacing;
03047     pData->m_BrushSpacingIncrConst = m_BrushSpacingIncrConst;
03048     pData->m_BrushSpacingIncrProp = m_BrushSpacingIncrProp;
03049     pData->m_BrushSpacingMaxRand = m_BrushSpacingMaxRand;
03050     pData->m_BrushSpacingRandSeed = m_BrushSpacingRandSeed;
03051 
03052     pData->m_PathOffsetType = m_PathOffsetType;
03053     pData->m_PathOffsetValue = m_PathOffsetValue;
03054     pData->m_PathOffsetIncrConst = m_PathOffsetIncrConst;
03055     pData->m_PathOffsetIncrProp = m_PathOffsetIncrProp;
03056     pData->m_OffsetValueMaxRand = m_OffsetValueMaxRand;
03057     pData->m_OffsetValueRandSeed = m_OffsetValueRandSeed;
03058     pData->m_OffsetTypeRandSeed = m_OffsetTypeRandSeed;
03059 
03060     pData->m_bTile = m_bTile;
03061 
03062     pData->m_SequenceType = m_SequenceType;
03063     pData->m_SequenceRandSeed = m_SequenceRandSeed;
03064 
03065     pData->m_bUseLocalFillColour = FALSE;
03066     
03067     pData->m_BrushHueIncrement = m_BrushHueIncrement;
03068     pData->m_BrushHueMaxRand   = m_BrushHueMaxRand;
03069     pData->m_BrushHueRandSeed = m_BrushHueRandSeed;
03070 
03071     pData->m_BrushSatIncrement = m_BrushSatIncrement;
03072     pData->m_BrushSatMaxRand   = m_BrushSatMaxRand;
03073     pData->m_BrushSatRandSeed  = m_BrushSatRandSeed;
03074 
03075     pData->m_BrushTransparency = m_BrushTransparency;
03076     pData->m_TranspMaxPressure = m_TranspMaxPressure;
03077 
03078     if (m_TimeStampPeriod <=0)
03079     {
03080         pData->m_bTimeStampBrushes  = FALSE;
03081         pData->m_TimeStampPeriod    = UINT32(-1);
03082     }
03083     else
03084     {
03085         pData->m_bTimeStampBrushes = TRUE;
03086         pData->m_TimeStampPeriod = (UINT32)m_TimeStampPeriod;
03087     }
03088 
03089     pData->m_Name = *GetLineName();
03090 }
03091 
03092 
03093 
03094 /********************************************************************************************
03095 
03096 >   BrushData BrushDefinition::GetBrushData() 
03097 
03098     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03099     Created:    6/10/99
03100     Inputs:     -
03101     Returns:    our brush data object
03102     Purpose:    gets the latest data from our path processor, copies it into our BrushData object 
03103                 which is then returned.  Note that you are responsible for deleting this object.
03104     SeeAlso:    -
03105 
03106 ********************************************************************************************/
03107 
03108 BrushData* BrushDefinition::GetBrushData()
03109 {
03110     BrushData* pNewData = new BrushData;
03111     if (pNewData != NULL)
03112         InitialiseBrushData(pNewData);
03113     return pNewData;
03114 }
03115 
03116 /********************************************************************************************
03117 
03118 >   BrushData BrushDefinition::GetBrushData() 
03119 
03120     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03121     Created:    6/10/99
03122     Inputs:     -
03123     Returns:    our brush data object
03124     Purpose:    gets the latest data from our path processor, copies it into our BrushData object 
03125                 which is then returned.  Note that you are responsible for deleting this object.
03126     SeeAlso:    -
03127 
03128 ********************************************************************************************/
03129 
03130 void BrushDefinition::SetMembersFromData(BrushData Data)
03131 {
03132     m_BrushSpacing          = Data.m_BrushSpacing;
03133     m_BrushSpacingIncrProp  = Data.m_BrushSpacingIncrProp;
03134     m_BrushSpacingIncrConst = Data.m_BrushSpacingIncrConst;
03135     m_BrushSpacingMaxRand   = Data.m_BrushSpacingMaxRand;
03136     m_BrushSpacingRandSeed  = Data.m_BrushSpacingRandSeed;
03137 
03138     m_PathOffsetType      = Data.m_PathOffsetType;
03139     m_PathOffsetValue     = Data.m_PathOffsetValue;
03140     m_PathOffsetIncrProp  = Data.m_PathOffsetIncrProp;
03141     m_PathOffsetIncrConst = Data.m_PathOffsetIncrConst;
03142     m_OffsetTypeRandSeed  = Data.m_OffsetTypeRandSeed;
03143     m_OffsetValueMaxRand  = Data.m_OffsetValueMaxRand;
03144     m_OffsetValueRandSeed = Data.m_OffsetValueRandSeed;
03145 
03146     m_bRotate             = Data.m_bRotate;
03147     m_RotateAngle         = Data.m_RotateAngle;
03148     m_RotationMaxRand     = Data.m_RotationMaxRand;
03149     m_RotationRandSeed    = Data.m_RotationRandSeed;
03150     m_RotAngleIncrConst   = Data.m_RotAngleIncrConst;
03151     m_RotAngleIncrProp    = Data.m_RotAngleIncrProp;
03152     m_RotationMaxPressure = Data.m_RotationMaxPressure;
03153 
03154     m_bTile               = Data.m_bTile;
03155 
03156     m_BrushScaling          = Data.m_BrushScaling;
03157     m_BrushScalingIncr      = Data.m_BrushScalingIncr;
03158     m_BrushScalingIncrConst = Data.m_BrushScalingIncrConst;
03159     m_BrushScalingMaxRand   = Data.m_BrushScalingMaxRand;
03160     m_BrushScalingRandSeed  = Data.m_BrushScalingRandSeed;
03161     m_ScalingMaxPressure    = Data.m_ScalingMaxPressure;
03162     
03163     m_BrushHueIncrement     = Data.m_BrushHueIncrement;
03164     m_BrushHueMaxRand       = Data.m_BrushHueMaxRand;
03165     m_BrushHueRandSeed      = Data.m_BrushHueRandSeed;
03166 
03167     m_BrushSatIncrement     = Data.m_BrushSatIncrement;
03168     m_BrushSatMaxRand       = Data.m_BrushSatMaxRand;
03169     m_BrushSatRandSeed      = Data.m_BrushSatRandSeed;
03170 
03171     m_BrushTransparency     = Data.m_BrushTransparency;
03172     m_TranspMaxPressure     = Data.m_TranspMaxPressure;
03173 
03174     m_SequenceType        = Data.m_SequenceType;
03175     m_SequenceRandSeed    = Data.m_SequenceRandSeed;
03176 
03177     m_LargestBoundingBox.MakeEmpty();
03178 
03179     m_Name = TEXT("Custom Brush");
03180 
03181     m_TimeStampPeriod = Data.m_TimeStampPeriod;
03182 
03183 
03184 }
03185 
03186 
03187 /********************************************************************************************
03188 
03189 >   UINT32 BrushDefinition::GetFirstRandomNumber(UINT32 Seed = 0) 
03190 
03191     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03192     Created:    6/10/99
03193     Inputs:     a seed to use to generate the random number sequence
03194     Returns:    the first number in a random number sequence
03195     Purpose:    Seeds srand with either the seed supplied or by using time (i.e. a random seed)
03196     SeeAlso:
03197 
03198 ********************************************************************************************/
03199 
03200 UINT32 BrushDefinition::GetFirstRandomNumber(UINT32 Seed)
03201 {
03202     // seed the random number generator
03203     if (Seed == 0)
03204         srand( (unsigned)time( NULL ) );
03205     else
03206         srand((unsigned)Seed);
03207 
03208     return (UINT32)rand();
03209 }
03210 
03211 
03212 /********************************************************************************************
03213 
03214 >   UINT32 BrushDefinition::GetNextRandomNumber() 
03215 
03216     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03217     Created:    6/10/99
03218     Inputs:     -
03219     Returns:    the next number in an already seeded random number sequence
03220     Purpose:    as above, note that you MUST have already called GetFirstRandomNumber()
03221     SeeAlso:
03222 
03223 ********************************************************************************************/
03224 
03225 UINT32 BrushDefinition::GetNextRandomNumber()
03226 {
03227     return (UINT32)rand();
03228 }
03229 
03230 
03231 /********************************************************************************************
03232 
03233 >   BOOL  BrushDefinition::CopyInkTreeToClipboard() 
03234 
03235     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03236     Created:    6/10/99
03237     Inputs:     -
03238     Returns:    TRUE if successful, FALSE otherwise
03239     Purpose:    copies the ink objects of this brush definition to the clipboard so they can be
03240                 used elsewhere
03241     SeeAlso:    -
03242 
03243 ********************************************************************************************/
03244 
03245 BOOL BrushDefinition::CopyInkTreeToClipboard()
03246 {
03247     // first see if we can get the clipboard
03248     InternalClipboard *Clipboard = InternalClipboard::Instance();
03249     if (Clipboard == NULL || !Clipboard->PrepareForCopy())
03250     {
03251         ERROR3("Error copying to clipboard");
03252         return FALSE;
03253     }
03254 
03255     if (m_pTree == NULL)
03256     {
03257         ERROR3("No ink objects");
03258         return FALSE;
03259     }
03260 
03261     // remember that we store the ink nodes in a spread, so the first child
03262     // will be the layer, which we do not want to copy
03263     Node* pFirstNode = m_pTree->FindFirstChild();
03264     if (pFirstNode == NULL)
03265     {
03266         ERROR3("No layer underneath spread");
03267         return FALSE;
03268     }
03269     pFirstNode = pFirstNode->FindFirstChild();
03270     
03271     // Just be sure its an ink node
03272     if (pFirstNode == NULL || !pFirstNode->IsAnObject())
03273     {
03274         ERROR3("No ink object to copy");
03275         return FALSE;
03276     }
03277 
03278     // we want to set up a range to copy to the clipboard, so find the rightmost sibling 
03279     // of our node
03280 
03281     // We need to set them unselected so that range::findfirst doesn't return NULL
03282 
03283     Node* pLastNode = pFirstNode;
03284     Node* pNextNode = pLastNode->FindNext();
03285     while (pNextNode != NULL)
03286     {
03287         pNextNode->SetSelected(FALSE);
03288         pLastNode = pNextNode;
03289         pNextNode = pLastNode->FindNext();
03290     }
03291     pFirstNode->SetSelected(FALSE);
03292     DocCoord Centre;
03293     if (pFirstNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
03294     {
03295         DocRect BRect = ((NodeRenderableInk*)pFirstNode)->GetBoundingRect();
03296         Centre = BRect.Centre();
03297         TRACEUSER( "Diccon", _T("Ink node centre = %d, %d\n"), Centre.x, Centre.y);
03298     }
03299     Node* pChild = pFirstNode->FindFirstChild(CC_RUNTIME_CLASS(AttrRadialTranspFill));
03300     if (pChild != NULL)
03301     {
03302         DocCoord *pStartPoint = ((AttrRadialTranspFill*)pChild)->GetStartPoint();
03303         if (pStartPoint != NULL)
03304             TRACEUSER( "Diccon", _T("StartPoint pre-export = %d, %d\n"), pStartPoint->x, pStartPoint->y);
03305     }
03306 
03307 
03308     // that should give us our range, now set up the range control, just use the default
03309     RangeControl rc;
03310     rc.Unselected = TRUE;
03311     rc.Selected = FALSE;
03312 
03313     Range BrushRange(pFirstNode, pLastNode, rc);
03314 
03315     PreExportSubTree();
03316     
03317     BOOL ok =  Clipboard->CopyObjects(BrushRange);
03318     BOOL StillOk = Clipboard->CopyCompleted();
03319 
03320     PostExportSubTree();
03321 
03322     return (ok && StillOk);
03323 }
03324     
03325 /********************************************************************************************
03326 
03327 >   BOOL BrushDefinition::ExportBrush(BaseCamelotFilter *pFilter)
03328 
03329     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03330     Created:    22/12/99
03331 
03332     Inputs:     pFilter - the BaseCamelotFilter filter that is being used to export a file.
03333                 Handle - the handle assigned to the brush
03334     Returns:    TRUE if export was successful
03335                 FALSE if export was aborted - no error is set, as in this case, it usually
03336                 means that the Brush has been deleted, and is being treated as an old-style
03337                 line. In this case, the caller should simply not bother exporting the
03338                 attribute using the Brush definition.
03339 
03340     Purpose:    To export a Brush definition. 
03341 
03342     Notes:      Do not call this function directly, it is better to call it via 
03343                 BrushComponent::ExportBrush as this ensures that each brush is only saved once
03344 
03345 ********************************************************************************************/
03346 
03347 BOOL BrushDefinition::ExportBrush(BaseCamelotFilter* pFilter,  BrushHandle Handle)
03348 {
03349     ERROR2IF(pFilter == NULL, FALSE, "Filter is null");
03350     ERROR2IF(Handle == BrushHandle_NoBrush, FALSE, "Trying to export null brush");
03351 
03352     BOOL ok = TRUE;
03353 
03354     PreExportSubTree();
03355     CXaraFileRecord Record(TAG_BRUSHDEFINITION, TAG_BRUSHDEFINITION_SIZE);
03356     if (ok) ok = Record.Init();
03357     
03358     // first write the handle
03359     if (ok) ok = Record.WriteUINT32(Handle);
03360     if (ok) pFilter->Write(&Record);
03361 
03362     // then write the subtree - note that this may be moved to the superclass
03363     if (ok)
03364     {
03365         Node* pExportNode = NULL;
03366         if (m_pTree == NULL)
03367             ok = FALSE;
03368         else
03369         {
03370             pExportNode = m_pTree->FindFirstChild();    // Find the Layer
03371             if (pExportNode != NULL)
03372                 pExportNode = pExportNode->FindFirstChild();    // Find the inknode
03373         }
03374 
03375         // Write out the clipart subtree. We have to encapsulate it in DOWN and UP
03376         // records ourselves
03377         CXaraFileRecord DownRec(TAG_DOWN, 0);
03378         if (ok) pFilter->Write(&DownRec);
03379 
03380         if (ok) ok = pFilter->WriteNodes(pExportNode);
03381 
03382         CXaraFileRecord UpRec(TAG_UP, 0);
03383         if (ok) pFilter->Write(&UpRec);
03384         
03385     }
03386     PostExportSubTree();
03387 
03388     // now write the data, note that the handle is written here also as they
03389     // are retrieved separately and will need to be reconciled
03390     CXaraFileRecord DataRecord((INT32)TAG_BRUSHDATA, (INT32)TAG_BRUSHDATA_SIZE);
03391     if (ok) ok = DataRecord.Init();
03392     
03393     BYTE Flags = 0;
03394     if (m_bTile) 
03395         Flags |= TAG_BRUSHTILE_FLAG;
03396     if (m_bRotate)
03397         Flags |= TAG_BRUSHROTATE_FLAG;
03398 
03399 
03400     INT32 Offset = (INT32)m_PathOffsetType;
03401 
03402     if(ok)  ok = DataRecord.WriteUINT32((UINT32)Handle);
03403     if (ok) ok = DataRecord.WriteINT32(m_BrushSpacing);
03404     if (ok) ok = DataRecord.WriteBYTE(Flags);
03405     if (ok) ok = DataRecord.WriteDOUBLE(m_RotateAngle);
03406     if (ok) ok = DataRecord.WriteINT32(Offset);
03407     if (ok) ok = DataRecord.WriteINT32(m_PathOffsetValue); 
03408     if (ok) ok = DataRecord.WriteUnicode((TCHAR *)*(GetLineName()));
03409     if (ok) ok = DataRecord.WriteDOUBLE(m_BrushScaling);
03410     if (ok) pFilter->Write(&DataRecord);
03411     
03412     // write the additional data
03413     CXaraFileRecord NextRec(TAG_MOREBRUSHDATA, TAG_MOREBRUSHDATA_SIZE);
03414     if (ok) ok = NextRec.Init();
03415     if (ok) ok = NextRec.WriteDOUBLE(m_BrushSpacingIncrProp);
03416     if (ok) ok = NextRec.WriteINT32(m_BrushSpacingIncrConst);
03417     if (ok) ok = NextRec.WriteINT32((INT32)m_BrushSpacingMaxRand);
03418     if (ok) ok = NextRec.WriteINT32((INT32)m_BrushSpacingRandSeed);
03419 
03420     if (ok) ok = NextRec.WriteDOUBLE(m_BrushScalingIncr);
03421     if (ok) ok = NextRec.WriteINT32((INT32)m_BrushScalingMaxRand);
03422     if (ok) ok = NextRec.WriteINT32((INT32)m_BrushScalingRandSeed);
03423 
03424     if (ok) ok = NextRec.WriteINT32((INT32)m_SequenceType);
03425     if (ok) ok = NextRec.WriteINT32((INT32)m_SequenceRandSeed);
03426 
03427     if (ok) ok = NextRec.WriteDOUBLE(m_PathOffsetIncrProp);
03428     if (ok) ok = NextRec.WriteINT32(m_PathOffsetIncrConst);
03429     if (ok) ok = NextRec.WriteINT32((INT32)m_OffsetTypeRandSeed);
03430     if (ok) ok = NextRec.WriteINT32((INT32)m_OffsetValueMaxRand);
03431     if (ok) ok = NextRec.WriteINT32((INT32)m_OffsetValueRandSeed);
03432     if (ok) ok = pFilter->Write(&NextRec);
03433 
03434     CXaraFileRecord AnotherRec(TAG_EVENMOREBRUSHDATA, TAG_EVENMOREBRUSHDATA_SIZE);
03435     if (ok) ok = AnotherRec.Init();
03436     if (ok) ok = AnotherRec.WriteINT32((INT32)m_RotationMaxRand);
03437     if (ok) ok = AnotherRec.WriteINT32((INT32)m_RotationRandSeed);
03438     if (ok) ok = pFilter->Write(&AnotherRec);
03439     
03440     CXaraFileRecord PressureRec(TAG_BRUSHPRESSUREINFO, TAG_BRUSHPRESSUREINFO_SIZE);
03441     if (ok) ok = PressureRec.Init();
03442     if (ok) ok = PressureRec.WriteINT32((INT32)m_ScalingMaxPressure);
03443     if (ok) ok = PressureRec.WriteINT32((INT32)m_SpacingMaxPressure);
03444     if (ok) ok = PressureRec.WriteINT32((INT32)m_OffsetMaxPressure);
03445     if (ok) ok = PressureRec.WriteINT32((INT32)m_RotationMaxPressure);
03446     if (ok) ok = PressureRec.WriteINT32((INT32)m_HueMaxPressure);
03447     if (ok) ok = PressureRec.WriteINT32((INT32)m_SatMaxPressure);
03448     if (ok) ok = PressureRec.WriteINT32((INT32)m_TimeStampMaxPressure);
03449     if (ok) ok = pFilter->Write(&PressureRec);
03450     
03451     // now write our transparency info
03452     CXaraFileRecord TranspRec(TAG_BRUSHTRANSPINFO, TAG_BRUSHTRANSPINFO_SIZE);
03453     if (ok) ok = TranspRec.Init();
03454     if (ok) ok = TranspRec.WriteINT32(INT32(m_BrushTransparency));
03455     if (ok) ok = TranspRec.WriteINT32(INT32(m_TranspMaxPressure));
03456     if (ok) ok = TranspRec.WriteDOUBLE(m_RotAngleIncrConst);
03457     if (ok) ok = TranspRec.WriteDOUBLE(m_BrushScalingIncrConst);
03458     if (ok) ok = TranspRec.WriteINT32(INT32(m_BrushHueMaxRand));
03459     if (ok) ok = TranspRec.WriteINT32(INT32(m_BrushHueRandSeed));
03460     if (ok) ok = TranspRec.WriteINT32(INT32(m_BrushSatMaxRand));
03461     if (ok) ok = TranspRec.WriteINT32(INT32(m_BrushSatRandSeed));
03462     if (ok) ok = pFilter->Write(&TranspRec);
03463 
03464     // Finally, mark this stroke as having been written out so we don't do it again
03465     if (ok) SetIOStore(TRUE);
03466 
03467 
03468 
03469     return ok;
03470 
03471 }
03472 
03473 
03474 
03475 /********************************************************************************************
03476 
03477 >   BOOL BrushDefinition::PreExportSubTree() 
03478 
03479     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03480     Created:    6/10/99
03481     Inputs:     -
03482     Returns:    TRUE if successful, FALSE if something went wrong
03483     Purpose:    To perform various functions just prior to saving the subtree of the brush definition.
03484                 The function loops through the BrushRefs, finding the blendpaths of each and 
03485                 transforming their attribute maps back to the position that they were in when the 
03486                 brush was created.
03487     SeeAlso:    -
03488 
03489     Notes:      This function is required because if the attribute map is not saved out at the exact
03490                 position it was created it will become 'out of sync' with the blendpath it applies to.
03491                 Recall that upon reimporting the brush the blendpaths are generated from scratch
03492                 whereas the attributes are not.
03493 ********************************************************************************************/
03494 
03495 BOOL BrushDefinition::PreExportSubTree()
03496 {
03497     BrushRef* pBrushRef = GetFirstBrushRef();
03498     ERROR2IF(pBrushRef== NULL, FALSE, "No brushref");
03499     while (pBrushRef != NULL)
03500     {
03501         BlendPath * pBlendPath = pBrushRef->GetFirstBlendPath();
03502         while (pBlendPath != NULL)
03503         {
03504             if (!pBlendPath->TransformBrushAttributesBeforeSave())
03505                 ERROR2(FALSE, "Somethings gone wrong");
03506             pBlendPath = pBrushRef->GetNextBlendPath(pBlendPath);
03507         }
03508         pBrushRef = GetNextBrushRef();
03509     }
03510     return TRUE;
03511 }
03512 
03513 
03514 
03515 /********************************************************************************************
03516 
03517 >   BOOL BrushDefinition::PostExportSubTree() 
03518 
03519     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03520     Created:    6/10/99
03521     Inputs:     -
03522     Returns:    TRUE if successful, FALSE if something went wrong
03523     Purpose:    To perform various functions just prior to saving the subtree of the brush definition.
03524                 The function loops through the BrushRefs, finding the blendpaths of each and undoes the
03525                 transformation performed by PreExportSubTree.
03526                 This is required because to continue using the brush in our current document we want 
03527                 to use its current position
03528             
03529     SeeAlso:    -
03530 
03531     Notes:      This function is required because if the attribute map is not saved out at the exact
03532                 position it was created it will become 'out of sync' with the blendpath it applies to.
03533                 Recall that upon reimporting the brush the blendpaths are generated from scratch
03534                 whereas the attributes are not.
03535 ********************************************************************************************/
03536 
03537 BOOL BrushDefinition::PostExportSubTree()
03538 {
03539     BrushRef* pBrushRef = GetFirstBrushRef();
03540 
03541     while (pBrushRef != NULL)
03542     {
03543         BlendPath * pBlendPath = pBrushRef->GetFirstBlendPath();
03544         while (pBlendPath != NULL)
03545         {
03546             if (!pBlendPath->TransformBrushAttributesAfterSave())
03547                 ERROR3("Somethings gone wrong");
03548             pBlendPath = pBrushRef->GetNextBlendPath(pBlendPath);
03549         }
03550         pBrushRef = GetNextBrushRef();
03551     }
03552     return TRUE;
03553 }
03554 
03555 
03556 
03557 
03558 
03559 
03560 
03561 
03562 /*-------------------------------------------------------------------------------------------
03563 ---------------------------------------------------------------------------------------------
03564 ---------------------------------------------------------------------------------------------
03565    The BrushComponent Class
03566 
03567 */
03568 
03569 
03570 /********************************************************************************************
03571 
03572 >   BOOL BrushComponentClass::Init()
03573 
03574     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03575     Created:    13/12/99
03576     Returns:    TRUE if all went well;
03577                 FALSE if not.
03578     Purpose:    Register the Brush document component with the main application.
03579     Errors:     Out of memory.
03580     SeeAlso:    DocComponent
03581 
03582 ********************************************************************************************/
03583 
03584 BOOL BrushComponentClass::Init()
03585 {
03586     // Instantiate a component class to register with the application.
03587     BrushComponentClass *pClass = new BrushComponentClass;
03588     if (pClass == NULL)
03589         return(FALSE);
03590 
03591     // Register it
03592     GetApplication()->RegisterDocComponent(pClass);
03593 
03594     return(TRUE);
03595 }
03596 
03597 
03598 /********************************************************************************************
03599 
03600 >   BOOL BrushComponentClass::LoadDefaultBrushes()
03601 
03602     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03603     Created:    13/12/99
03604     Returns:    TRUE if all went well;
03605                 FALSE if not.
03606     Purpose:    Loads default brushes from a file
03607     Errors:     Fail to load file   
03608 
03609 ********************************************************************************************/
03610 
03611 BOOL BrushComponentClass::LoadDefaultBrushes()
03612 {
03613     PORTNOTETRACE("other","BrushComponentClass::LoadDefaultBrushes - do nothing");
03614 #ifndef EXCLUDE_FROM_XARALX
03615     // lets try loading the default brushes here
03616     LoadBrushDirect LoadBrush;
03617     
03618     // set up the search path, file util allows us just to pass the path/*.xar
03619     String_256 SearchPath;
03620     CResDll::GetExecutablePath((TCHAR*)SearchPath);
03621     String_256 Path = TEXT("\\Templates\\Brushes\\");
03622     SearchPath += Path;
03623     String_256 FileSpecifier = SearchPath;
03624     FileSpecifier += TEXT("*.xar");
03625 
03626     BOOL ok = FileUtil::StartFindingFiles(&FileSpecifier);
03627     BrushComponent::BeginLoadingDefaultFiles();
03628     String_256 Filename;
03629     FilePath oFilePath;
03630     String_16 Extension;
03631     while (ok)
03632     {
03633         // fileutil will give us the next filename
03634         ok = FileUtil::FindNextFile(&Filename);
03635         String_256 FullPath = SearchPath;
03636         FullPath += Filename;
03637         if (ok)
03638         {
03639             oFilePath.SetFilePath(FullPath);
03640             Extension = oFilePath.GetType();
03641             Extension.toLower();
03642             if (oFilePath.IsValid() && Extension==String_16("xar"))
03643             {
03644                 BrushComponent::LoadNextDefaultFile();
03645                 ok = LoadBrush.Execute((TCHAR*)FullPath);
03646             }
03647         }
03648     }
03649     BrushComponent::EndLoadingDefaults();
03650     FileUtil::StopFindingFiles();
03651 #endif
03652     return TRUE;
03653 }
03654 /********************************************************************************************
03655 
03656 >   void BrushComponentClass::DeInit()
03657 
03658     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03659     Created:    13/12/99
03660 
03661     Returns:    TRUE if all went well;
03662                 FALSE if not.
03663 
03664     Purpose:    De-initialises the vector Brush provider system
03665 
03666 ********************************************************************************************/
03667 
03668 void BrushComponentClass::DeInit()
03669 {
03670     BrushComponent::DeleteList();
03671 }
03672 
03673 
03674 
03675 /********************************************************************************************
03676 
03677 >   BOOL BrushComponentClass::AddComponent(BaseDocument *pDocument)
03678 
03679     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03680     Created:    13/12/99
03681     Inputs:     pDocument - the document to add the component to.
03682     Returns:    TRUE if the Brush component was added ok;
03683                 FALSE if not.
03684     Purpose:    Add a Brush component to the specified document.
03685     Errors:     Out of memory
03686     SeeAlso:    PrintComponentClass
03687 
03688 ********************************************************************************************/
03689 
03690 BOOL BrushComponentClass::AddComponent(BaseDocument *pDocument)
03691 {
03692     ERROR2IF(pDocument==NULL, FALSE, "NULL document passed to BrushCompClass:Add");
03693 
03694     // Check to see if this document already has a colour list; if so, leave it alone.
03695     if (pDocument->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)) != NULL)
03696         return(TRUE);
03697 
03698     // Ok - create the print mark component.
03699     BrushComponent *pComponent = new BrushComponent;
03700     if (pComponent == NULL)
03701         return(FALSE);
03702 
03703     // All ok - add the component to the document.
03704     pDocument->AddDocComponent(pComponent);
03705 
03706     return(TRUE);
03707 }
03708 
03709 
03710 /*--------------------------------------------------------------------------------------------
03711 ----------------------------------------------------------------------------------------------
03712 ----------------------------------------------------------------------------------------------
03713         The BrushComponent class
03714 
03715 */
03716 
03717 UINT32 BrushComponent::m_CurrentDefaultFile = BRUSHFILE_NONE;
03718 
03719 /********************************************************************************************
03720 
03721 >   BrushComponent::BrushComponent()
03722 
03723     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03724     Created:    13/12/99
03725 
03726     Purpose:    Constructor
03727 
03728 ********************************************************************************************/
03729 
03730 BrushComponent::BrushComponent() : LineComponent()
03731 {
03732     m_pImportBrushDef = NULL;
03733     
03734 }
03735 
03736 
03737 
03738 /********************************************************************************************
03739 
03740 >   BrushComponent::~BrushComponent()
03741 
03742     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03743     Created:    13/12/99
03744 
03745     Purpose:    Destructor
03746 
03747 ********************************************************************************************/
03748 
03749 BrushComponent::~BrushComponent()
03750 {
03751     if (m_pImportBrushDef != NULL)
03752         delete m_pImportBrushDef;
03753 }
03754 
03755 
03756 /********************************************************************************************
03757 
03758 >   BOOL BrushComponent::BeginLoadingDefaultFiles(UINT32 NumFiles)
03759 
03760     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03761     Created:    6/10/99
03762     Inputs:     -
03763     Returns:    TRUE 
03764     Purpose:    Lets the component know that we are starting to load default brushes
03765     Notes:      What happens here is that every brush added to the component whilst 
03766                 m_CurrentDefaultBrush != BRUSHFILE_NONE will be assigned m_CurrentDefaultBrush
03767                 as its default file ID.
03768                 Note again, as you can tell from the code this can only be done once.
03769 ********************************************************************************************/
03770 
03771 BOOL BrushComponent::BeginLoadingDefaultFiles()
03772 {
03773     m_CurrentDefaultFile = BRUSHFILE_NONE;
03774     return TRUE;
03775 }
03776 
03777 
03778 /********************************************************************************************
03779 
03780 >   BOOL BrushComponent::LoadDefaultFile(String_256 Filename)
03781 
03782     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03783     Created:    6/10/99
03784     Inputs:    -
03785     Returns:    TRUE if all goes well
03786     Purpose:    Increments our default file counter  
03787     SeeAlso:    -
03788 
03789 ********************************************************************************************/
03790 
03791 BOOL BrushComponent::LoadNextDefaultFile()
03792 {   
03793     // is this the first file?
03794     if (m_CurrentDefaultFile == BRUSHFILE_NONE)
03795         m_CurrentDefaultFile = 0;
03796     else
03797         m_CurrentDefaultFile++;
03798 
03799     return TRUE;
03800 }
03801     
03802 
03803 
03804 /********************************************************************************************
03805 
03806 >   void BrushComponent::EndLoadingDefaults()
03807 
03808     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03809     Created:    6/10/99
03810     Inputs:     -
03811     Returns:    -
03812     Purpose:    Finishes loading default files
03813     SeeAlso:    -
03814 
03815 ********************************************************************************************/
03816 
03817 void BrushComponent::EndLoadingDefaults()
03818 {
03819     m_CurrentDefaultFile = BRUSHFILE_NONE;
03820 }
03821 
03822 /********************************************************************************************
03823 
03824 >   AttrBrushType* BrushComponent::CreateAttributeNode(BrushHandle Handle) 
03825 
03826     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03827     Created:    6/10/99
03828     Inputs:     Handle to the brush definition which we want to base this brush on
03829     Returns:    Attribute node based on this definition
03830     Purpose:    -
03831     SeeAlso:    -
03832 
03833 ********************************************************************************************/
03834 
03835 AttrBrushType* BrushComponent::CreateAttributeNode(BrushHandle Handle)
03836 {
03837     BrushDefinition* pBrushDef = FindBrushDefinition(Handle);
03838     if (pBrushDef == NULL)
03839         return NULL;
03840 
03841     AttrBrushType* pNewNode = new AttrBrushType;
03842     if (pNewNode == NULL)
03843         return NULL;
03844 
03845     BrushAttrValue* pVal = (BrushAttrValue*)pNewNode->GetAttributeValue();
03846     if (pVal == NULL)
03847         return NULL;
03848 
03849     PathProcessorBrush* pPathProc = new PathProcessorBrush;
03850     if (pPathProc == NULL)
03851         return NULL;
03852     pBrushDef->CopyDataToProcessor(pPathProc);
03853     pVal->SetPathProcessor(pPathProc);
03854 
03855     // tell it which brush definition to use
03856     pPathProc->SetBrushDefinition(Handle);
03857     return pNewNode;
03858 }
03859 
03860 
03861 /********************************************************************************************
03862 
03863 >   BOOL  BrushComponent::CopyInkObjectsToClipboard(BrushHandle Handle) 
03864 
03865     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03866     Created:    6/10/99
03867     Inputs:     Handle to the brush definition which we want to send to the clipboard
03868     Returns:    TRUE if successful, FALSE otherwise
03869     Purpose:    copies the ink objects of this brush definition to the clipboard so they can be
03870                 used elsewhere
03871     SeeAlso:    -
03872 
03873 ********************************************************************************************/
03874 
03875 BOOL BrushComponent::CopyInkObjectsToClipboard(BrushHandle Handle)
03876 {
03877     if (Handle == BrushHandle_NoBrush || Handle >= m_Used)
03878     {
03879         ERROR3("Invalid brush handle");
03880         return FALSE;
03881     }
03882 
03883     BrushDefinition* pBrushDef = (BrushDefinition*)m_pLineArray[Handle];
03884     if (pBrushDef == NULL)
03885     {
03886         ERROR3("Brush definition is NULL");
03887         return FALSE;
03888     }
03889     
03890     return pBrushDef->CopyInkTreeToClipboard();
03891 }
03892 
03893 /********************************************************************************************
03894 
03895 >   static AttrBrushType* BrushComponent::CreateNode(BrushHandle Handle) 
03896 
03897     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03898     Created:    6/10/99
03899     Inputs:     Handle to the brush definition which we want to base this brush on
03900     Returns:    Attribute node based on this definition
03901     Purpose:    static version of above
03902     SeeAlso:    -
03903 
03904 ********************************************************************************************/
03905 
03906 AttrBrushType* BrushComponent::CreateNode(BrushHandle Handle)
03907 {
03908     BrushDefinition* pBrushDef = FindBrushDefinition(Handle);
03909     if (pBrushDef == NULL)
03910         return NULL;
03911 
03912     AttrBrushType* pNewNode = new AttrBrushType;
03913     if (pNewNode == NULL)
03914         return NULL;
03915 
03916     BrushAttrValue* pVal = (BrushAttrValue*)pNewNode->GetAttributeValue();
03917     if (pVal == NULL)
03918         return NULL;
03919 
03920     PathProcessorBrush* pPathProc = new PathProcessorBrush;
03921     if (pPathProc == NULL)
03922         return NULL;
03923     pBrushDef->CopyDataToProcessor(pPathProc);
03924     pVal->SetPathProcessor(pPathProc);
03925 
03926     // tell it which brush definition to use
03927     pPathProc->SetBrushDefinition(Handle);
03928     return pNewNode;
03929 }
03930 
03931 
03932 /********************************************************************************************
03933 
03934 >   BOOL BrushComponent::StartExport(BaseCamelotFilter *pFilter)
03935 
03936     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03937     Created:    13/12/99
03938 
03939     Inputs:     pFilter - the BaseCamelotFilter filter that is being used to export a file.
03940     Returns:    TRUE if the component was able to prepare for exporting;
03941                 FALSE if not (e.g. out of memory)
03942 
03943     Purpose:    Called before an export is started
03944 
03945 ********************************************************************************************/
03946 
03947 BOOL BrushComponent::StartExport(BaseCamelotFilter *pFilter)
03948 {
03949 //  return TRUE; // for now
03950 #if !defined(EXCLUDE_FROM_RALPH)
03951     
03952     if (pFilter == NULL)
03953     {
03954         ERROR3("BrushComponent::StartExport filter is null!");
03955         return(TRUE);
03956     }
03957 
03958     // ****!!!!TODO - if we're multi-threadig, this probably needs to be a critical section
03959     // because the list is global
03960 
03961     // Flag all Brushs as not having been saved. When we save one, we set its flag so that
03962     // we don't try to save it a second time.
03963     if (m_pLineArray != NULL)
03964     {
03965         for (UINT32 Index = 0; Index < m_Used; Index++)
03966         {
03967             if (m_pLineArray[Index] != NULL)
03968                     m_pLineArray[Index]->SetIOStore(FALSE);
03969         }
03970 
03971         // Write out an atomic tag definition in front of the vector Brush definition.
03972         // ****!!!!TODO - This should really only be done just before we export the first
03973         // BrushDEFINITION tag, but it is not properly supported by the export system as yet.
03974         
03975         //TODO : Make tags for brush components!!
03976         
03977         BOOL ok = TRUE;
03978         CXaraFileRecord Rec(TAG_ATOMICTAGS, TAG_ATOMICTAGS_SIZE);
03979         if (ok) ok = Rec.Init();
03980         if (ok) ok = Rec.WriteUINT32(TAG_BRUSHDEFINITION);
03981         if (ok) pFilter->Write(&Rec);       // And write out the record
03982         
03983     }
03984 #endif
03985     return(TRUE);
03986 }
03987 
03988 
03989 /********************************************************************************************
03990 
03991 >   static BOOL ImportLine(CXaraFileRecord* pRecord)
03992 
03993     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03994     Created:    13/12/99
03995 
03996     Inputs:     pRecord - The TAG_BRUSHDEFINITION record to import
03997 
03998     Returns:    TRUE if Import was successful
03999 
04000     Purpose:    To import a vector Line definition
04001 
04002 ********************************************************************************************/
04003 
04004 BOOL BrushComponent::StartImportBrush(CamelotRecordHandler *pHandler, CXaraFileRecord *pRecord, 
04005                                       UINT32 ImportHandle)
04006 {
04007     m_ImportHandle = 0xffffffff;
04008     
04009     if (m_pImportPreviousContext != NULL)
04010     {
04011     //  delete m_pImportPreviousContext;
04012         m_pImportPreviousContext = NULL;
04013     }
04014 
04015     if (m_pImportNewLine != NULL)
04016     {
04017         m_pImportNewLine->CascadeDelete();
04018         m_pImportNewLine = NULL;
04019     }
04020 
04021     // Create a spread and set up the import system to import the brush into it
04022     // If this fails, then it'll just find somewhere "sensible" to import into
04023     m_pImportNewLine = new Spread;
04024     if (m_pImportNewLine == NULL)
04025         return(FALSE);
04026 
04027     Layer *pLineLayer = new Layer(m_pImportNewLine, FIRSTCHILD, String_256(TEXT("Jason did this")));
04028     if (pLineLayer == NULL)
04029     {
04030         delete m_pImportNewLine;
04031         m_pImportNewLine = NULL;
04032         return(FALSE);
04033     }
04034 
04035     // Now, remember where we were importing into, and point the importer at our brush tree
04036     m_pImportPreviousContext = pHandler->GetInsertContext();
04037     pHandler->SetInsertContextNode(pLineLayer);
04038 
04039     // check to see if our import brushdef already exists, if so delete it
04040     if (m_pImportBrushDef != NULL)
04041         delete m_pImportBrushDef;
04042     // make the new brush definition
04043     m_pImportBrushDef = new BrushDefinition(m_pImportNewLine);
04044     if (m_pImportBrushDef == NULL)
04045         return(FALSE);
04046 
04047 
04048 
04049     // Remember the handle used for the Brush in the file with the Brush so that
04050     // we can map any incoming handles into the real handles we are using internally.
04051     m_pImportBrushDef->SetIOStore(ImportHandle & 0x00ffffff);
04052 
04053 
04054     /* in case you were wondering, after this function the import goes as follows:
04055     - Ink nodes etc. are imported into m_pImportNewLine
04056     - Brush data is imported
04057     - EndImportBrush is called, where the new brush definition is inserted
04058     */
04059     
04060 
04061 
04062     return(TRUE);
04063 }
04064 
04065 
04066 /********************************************************************************************
04067 
04068 >   BOOL BrushComponent::EndImportBrush(CamelotRecordHandler *pHandler);
04069 
04070     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04071     Created:    13/12/99
04072 
04073     Inputs:     pRecord - The TAG_BRUSHDEFINITION record to import
04074 
04075     Returns:    TRUE if Import was successful
04076 
04077     Purpose:    To import a vector brush definition
04078 
04079 ********************************************************************************************/
04080 
04081 BOOL BrushComponent::EndImportBrush(CamelotRecordHandler *pHandler)
04082 {
04083     ERROR2IF(m_pImportPreviousContext == NULL,FALSE, "EndImportBrush - something hasn't gone too well");
04084     ERROR2IF(m_pImportBrushDef == NULL, FALSE, "ImportBrushDef is NULL at EndImportBrush");
04085     
04086     // Restore the previous import context node
04087     pHandler->RestoreInsertContext(m_pImportPreviousContext);
04088     delete m_pImportPreviousContext;
04089     m_pImportPreviousContext = NULL;
04090 
04091     // --- Now, convert all IndexedColours (which are document-dependent) into standalone DocColours
04092     // This wouldn't be necessary, except that the DocColours we saved have magically been turned
04093     // back into local Indexedcolours by the export/import process.
04094     // BLOCK
04095 
04096     LineDefinition::ConvertIndexedColours((Spread*)m_pImportNewLine);
04097 
04098     // Create a new Brush definition from the imported brush    
04099     if (m_pImportBrushDef->GenerateBrush() != TRUE)
04100         return FALSE;
04101     
04102     m_pImportBrushDef->CalculateMaxScaling();
04103 
04104     // add the item,
04105     /*BrushHandle NewHandle =*/ AddNewItem(m_pImportBrushDef); 
04106 
04107     CleanUpAfterImport();
04108 
04109     return TRUE;
04110     
04111     
04112 }
04113 
04114 
04115 
04116 
04117 
04118 
04119 /********************************************************************************************
04120 
04121 >   BOOL ExportBrush(BaseCamelotFilter *pFilter, BrushHandle Handle)
04122 
04123     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04124     Created:    22/12/99
04125 
04126     Inputs:     pFilter - the BaseCamelotFilter filter that is being used to export a file.
04127                 Handle  - The Brush to be exported
04128 
04129     Returns:    TRUE if export was successful
04130                 FALSE if export was aborted - no error is set, as in this case, it usually
04131                 means that the Brush has been deleted, and is being treated as an old-style
04132                 line. In this case, the caller should simply not bother exporting the
04133                 attribute using the Brush definition.
04134 
04135     Purpose:    To export a vector Brush definition. 
04136 
04137     Notes:      Brush definitions (like colours) are only saved out when a node in the
04138                 tree is found which makes use of the Brush. You should call this function
04139                 before exporting any attribute which uses the Brush definition. It
04140                 automatically checks if the Brush has already been saved, and will not save
04141                 the definition more than once.
04142 
04143                 When saving your reference to the Brush, save out the Brush's Handle
04144                 as it's unique ID word.
04145 
04146 ********************************************************************************************/
04147 
04148 BOOL BrushComponent::ExportLine(BaseCamelotFilter *pFilter, BrushHandle Handle)
04149 {
04150     ERROR3IF(pFilter == NULL, "Illegal NULL params");
04151 
04152     // Find the stroke, and baulk if it's all gone wrong
04153     BrushDefinition *pBrush = FindBrushDefinition(Handle);
04154     if (pBrush == NULL)
04155     {
04156         ERROR3("Attempt to save a deleted or non-existent stroke");
04157         return(FALSE);
04158     }
04159 
04160     // Check if the definition has already been saved, in which case we don't need to do anything more
04161     if (pBrush->ReadIOStore())
04162         return(TRUE);
04163 
04164     // We've got a stroke definition now, get it to write itself to the file
04165     return pBrush->ExportBrush(pFilter, Handle);
04166     
04167 }
04168 
04169 
04170 /********************************************************************************************
04171 
04172 >   static BrushHandle BrushComponent::FindImportedBrush(UINT32 ImportedHandle)
04173 
04174     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04175     Created:    22/12/99
04176 
04177     Inputs:     Importedhandle - The handle which is used in the file being imported
04178                                  to reference the stroke.
04179 
04180     Returns:    The BrushHandle of the loaded stroke, or BrushHandle_NoBrush
04181                 if the stroke could not be found.
04182 
04183     Purpose:    To match up a handle from the currently importing file to the
04184                 real internal BrushHandle of the imported BrushDefinition
04185 
04186 ********************************************************************************************/
04187 
04188 BrushHandle BrushComponent::FindImportedBrush(UINT32 ImportedHandle)
04189 {
04190     ImportedHandle &= 0x00ffffff;   // Only the bottom 24 bits are relevant
04191     for (UINT32 Index = 0; Index < m_Used; Index++)
04192     {
04193         if (m_pLineArray[Index] != NULL && m_pLineArray[Index]->ReadIOStore() == ImportedHandle)
04194             return((BrushHandle)Index);
04195     }
04196 
04197     return(BrushHandle_NoBrush);
04198 }
04199 
04200 
04201 
04202 /********************************************************************************************
04203 
04204 >   static BrushDefinition *BrushComponent::FindBrushDefinition(UINT32 Handle, BOOL IncludeDeactiveated);
04205 
04206     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04207     Created:    13/12/99
04208 
04209     Inputs:     Handle - A handle which uniquely identifies the new stroke
04210                 IncludeDeactivated - flag to say that we wish to include deactivated definitions, 
04211                 defaults to false
04212     Returns:    A pointer to a StrokeDefinition for that Stroke.
04213                 If the stroke has been deleted, NULL will be returned, in which case,
04214                 you should gracefully degrade (by rendering an old style Brush in place of
04215                 the stroke)
04216 
04217     Purpose:    Find a Brush definition, given its unique identity handle
04218 
04219 ********************************************************************************************/
04220 
04221 BrushDefinition *BrushComponent::FindBrushDefinition(BrushHandle Handle, BOOL IncludeDeactivated)
04222 {
04223     if (Handle < 0)
04224     {
04225         ERROR3("Negative brush handle");
04226         return NULL;
04227     }
04228     if (Handle == BrushHandle_NoBrush)
04229         return(NULL);
04230 
04231     if (Handle >= m_Used)
04232     {
04233         ERROR3("Out of range Brush handle");
04234         return(NULL);
04235     }
04236     
04237     BrushDefinition* pDef = ((BrushDefinition*)m_pLineArray[Handle]);
04238     
04239     if (!pDef->IsActivated() && !IncludeDeactivated)
04240         pDef = NULL;
04241 
04242     return pDef;
04243 }
04244 
04245 
04246 /******************************************************************************************
04247 
04248 >   static BOOL BrushComponent::ExpandArray(void)
04249 
04250     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04251     Created:    28/2/97
04252 
04253     Outputs:    On succesful exit, the member array of BrushDefinition pointers will be bigger
04254     Returns:    FALSE if it failed to allocate memory
04255 
04256     Purpose:    (Internal method)
04257                 Expands the storage structure of the Brush list to allow more entries to be
04258                 used. Called automatically by AddNewBrush as necessary.
04259 
04260     Notes:      Internal storage is an array of pointers to BrushDefinitions
04261                 NULL pointers beyond (& including) "Used" indicate free slots.
04262                 NULL pointers before "Used" indicate deleted Brushs - these slots
04263                 should NOT be re-used, as there may still be references to them in
04264                 the system.
04265 
04266 ******************************************************************************************/
04267 
04268 BOOL BrushComponent::ExpandArray(void)
04269 {
04270     // ****!!!!TODO - if we're multi-threading, this probably needs to be a critical section
04271     // because the list is global
04272     
04273     const INT32 AllocSize = m_CurrentSize + 64;
04274 
04275     if (m_pLineArray == NULL)
04276     {
04277         m_pLineArray = (LineDefinition **) CCMalloc(AllocSize * sizeof(LineDefinition *));
04278         if (m_pLineArray == NULL)
04279             return(FALSE);
04280     }
04281     else
04282     {
04283         // We have an array - we must make it larger
04284         LineDefinition **pNewBuf = (LineDefinition **)
04285                                     CCRealloc(m_pLineArray, AllocSize * sizeof(LineDefinition *));
04286         if (pNewBuf == NULL)
04287             return(FALSE);
04288 
04289         m_pLineArray = pNewBuf;
04290     }
04291 
04292     // Success. Initalise all the new pointers to NULL
04293     for (UINT32 i = m_Used; i < m_CurrentSize; i++)
04294             m_pLineArray[i] = NULL;
04295 
04296     // Update the current size value, and return success
04297     m_CurrentSize = (UINT32)AllocSize;
04298     return(TRUE);
04299     
04300 
04301 }
04302 
04303 
04304 
04305 
04306 /********************************************************************************************
04307 
04308 >   BrushDefinition *BrushComponent::GetImportedBrushDefinition()
04309 
04310     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04311     Created:    13/12/99
04312     Inputs:     -
04313     Returns:    A pointer to the brush definition that is currently in the process of being 
04314                 imported.
04315 
04316     Purpose:    As above, note that this function is only useful in the period between 
04317                 StartImportBrush and EndImportBrush being called. At all other times
04318                 m_pImportBrushDef should be NULL.
04319 
04320 ********************************************************************************************/
04321 
04322 BrushDefinition* BrushComponent::GetImportBrushDefinition()
04323 {
04324     return m_pImportBrushDef;
04325 }
04326 
04327 
04328 
04329 /********************************************************************************************
04330 
04331 >   void BrushComponent::CleanUpAfterImport()
04332 
04333     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04334     Created:    13/12/99
04335     Inputs:     -
04336     Returns:    -
04337 
04338     Purpose:    Deletes the objects we created for import.  Goes without saying that
04339                 calling this function before you have added the brushdef to the component is
04340                 pretty silly.
04341 
04342 ********************************************************************************************/
04343 
04344 void BrushComponent::CleanUpAfterImport()
04345 {
04346     // don't delete the brushdef as it is now being used in the component
04347     if (m_pImportBrushDef != NULL)
04348          m_pImportBrushDef = NULL;
04349 
04350     if (m_pImportNewLine != NULL)
04351         m_pImportNewLine = NULL;
04352 }
04353 
04354 
04355 /********************************************************************************************
04356 
04357 >   void BrushDefinition::CopyDataToPathProcessor(PathProcessorBrush* pPathProc) 
04358 
04359     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04360     Created:    6/10/99
04361     Inputs:     pPathProc - path processor to receive the data
04362     Returns:    -
04363     Purpose:    To copy all of the numeric data about this brush to a path processor 
04364     SeeAlso:    -
04365 
04366 ********************************************************************************************/
04367 
04368 void BrushDefinition::CopyDataToProcessor(PathProcessorBrush* pPathProc)
04369 {
04370     if (pPathProc == NULL)
04371     {
04372         ERROR3("Path processor is NULL");
04373         return;
04374     }
04375     
04376     // spacing members
04377     pPathProc->SetSpacing(m_BrushSpacing);
04378     pPathProc->SetSpacingIncrProp(m_BrushSpacingIncrProp);  
04379     pPathProc->SetSpacingIncrConst(m_BrushSpacingIncrConst);
04380     pPathProc->SetSpacingMaxRand(m_BrushSpacingMaxRand);
04381     pPathProc->SetSpacingRandSeed(m_BrushSpacingRandSeed);
04382     
04383     // offset members
04384     pPathProc->SetPathOffsetType(m_PathOffsetType);
04385     pPathProc->SetPathOffsetValue(m_PathOffsetValue);
04386     pPathProc->SetPathOffsetIncrConst(m_PathOffsetIncrConst);
04387     pPathProc->SetPathOffsetIncrProp(m_PathOffsetIncrProp);
04388     pPathProc->SetOffsetTypeRandSeed(m_OffsetTypeRandSeed);
04389     pPathProc->SetOffsetValueMaxRand(m_OffsetValueMaxRand);
04390     pPathProc->SetOffsetValueRandSeed(m_OffsetValueRandSeed);
04391     
04392     
04393     // scaling members
04394     pPathProc->SetBrushScaling(m_BrushScaling);
04395     pPathProc->SetScalingMaxRand(m_BrushScalingMaxRand);
04396     pPathProc->SetScalingRandSeed(m_BrushScalingRandSeed);
04397     pPathProc->SetScalingMaxPressure(m_ScalingMaxPressure);
04398     pPathProc->SetMaxScaling(m_MaxScaling);
04399     pPathProc->SetBrushScalingIncr(m_BrushScalingIncr);
04400     pPathProc->SetBrushScalingIncrConst(m_BrushScalingIncrConst);
04401     
04402 
04403     // rotation
04404     pPathProc->SetRotationMaxRand(m_RotationMaxRand);
04405     pPathProc->SetRotationRandSeed(m_RotationRandSeed);
04406     pPathProc->SetRotationIncrConst(m_RotAngleIncrConst);
04407     pPathProc->SetRotationIncrProp(m_RotAngleIncrProp);
04408     pPathProc->SetRotationMaxPressure(m_RotationMaxPressure);
04409     pPathProc->SetRotationAngle(m_RotateAngle);
04410 
04411     
04412     // sequence
04413     pPathProc->SetSequenceType(m_SequenceType);
04414     pPathProc->SetSequenceSeed(m_SequenceRandSeed);
04415 
04416     // Hue/Saturation
04417     pPathProc->SetHueIncrement(m_BrushHueIncrement);
04418     pPathProc->SetHueMaxRand(m_BrushHueMaxRand);
04419     pPathProc->SetHueRandSeed(m_BrushHueRandSeed);
04420     pPathProc->SetSatIncrement(m_BrushSatIncrement);
04421     pPathProc->SetSatMaxRand(m_BrushSatMaxRand);
04422     pPathProc->SetSatRandSeed(m_BrushSatRandSeed);
04423 
04424     // Transparency
04425     pPathProc->SetBrushTransparency(m_BrushTransparency);
04426     pPathProc->SetTransparencyPressure(m_TranspMaxPressure);
04427 
04428     // Other
04429     pPathProc->SetRotated(m_bRotate);
04430     pPathProc->SetTiling(m_bTile);
04431 }
04432 
04433 
04434 /********************************************************************************************
04435 
04436 >   static LineHandle LineComponent::AddNewItem(LineDefinition *pLine, BOOL AskName = FALSE)
04437 
04438     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04439     Created:    13/12/99
04440 
04441     Inputs:     pLine - (may not be NULL) A Line definition to add, which now
04442                           belongs to the LineComponent, so you mustn't delete it!
04443                 AskName - a flag saying whether or not we should prompt the user for a name, 
04444                 defaults to FALSE
04445     Returns:    A handle which uniquely identifies the new Line, or
04446                 LineHandle_NoLine if we ran out of memory for storing Lines
04447 
04448     Purpose:    Adds the given Line to the global Line list.
04449 
04450     Notes:      Also read the notes in LineComponent::AddNewItem
04451                 This function overrides the base class but actually uses it
04452                 to do the actual adding.  functinality added here is that
04453                 it works out whether or not the brush has actually been added
04454                 and if so adds it to the line gallery
04455 
04456 ********************************************************************************************/
04457 
04458 LineHandle BrushComponent::AddNewItem(LineDefinition *pItem, BOOL AskName)
04459 {
04460     // just make sure its the right type
04461     ERROR2IF(!pItem->IsKindOf(CC_RUNTIME_CLASS(BrushDefinition)), 
04462             BrushHandle_NoBrush, "Attempting to pass in wrong definition");
04463     String_32 DefaultName(_R(IDS_BRUSH_DEFAULT_NAME));
04464     m_NewName = DefaultName;
04465     m_bCancelNewBrush = FALSE;
04466     if (AskName == TRUE)
04467     {
04468         // launch the naming dialog, it will either set m_NewName or tell us to cancel
04469         OpDescriptor* pDesc = OpDescriptor::FindOpDescriptor( OPTOKEN_INITNAME_BRUSH_DLG );
04470         if (pDesc != NULL)
04471         {
04472             pDesc->Invoke();
04473         }
04474     
04475         // did they cancel it?
04476         if (m_bCancelNewBrush)
04477         {
04478             m_bCancelNewBrush = FALSE;
04479             return BrushHandle_NoBrush;
04480         }
04481         
04482         pItem->SetLineName(&m_NewName);
04483     }
04484 
04485     // stash the old number of brushes, which will be incremented if we make a new one
04486     UINT32 OldNumBrushes = m_Used;
04487 
04488     // item is added in the base class
04489     LineHandle NewHandle = LineComponent::AddNewItem(pItem);
04490  
04491     // have we actually added a new brush?
04492     if (NewHandle >= OldNumBrushes && NewHandle != BrushHandle_NoBrush)
04493     {       
04494         // tell it the filename ID
04495         ((BrushDefinition*)pItem)->SetBrushFileID(m_CurrentDefaultFile);
04496 
04497         // make a new atttibute to add to the line gallery
04498         PathProcessorBrush* pNewPathProc = new PathProcessorBrush;
04499         if (pNewPathProc == NULL)
04500         {
04501             ERROR3("Failed to allocate path processor");
04502             return NewHandle;
04503         }
04504 
04505         // tell it which brush definition to use
04506         pNewPathProc->SetBrushDefinition(NewHandle);
04507 
04508         // transfer all the data
04509         ((BrushDefinition*)pItem)->CopyDataToProcessor(pNewPathProc);
04510         // make a new attribute value for use by the line gallery
04511         BrushAttrValue* pVal = new BrushAttrValue(pNewPathProc);
04512         if (pVal == NULL)
04513         {
04514             ERROR3("Unable to allocate new BrushAttrVal");
04515             return NewHandle;
04516         }
04517     
04518         // add it to the line gallery
04519         LineGallery::AddNewBrushItem(pVal); 
04520 
04521         // get the freehand tool
04522         ToolListItem* pToolItem = Tool::Find(TOOLID_FREEHAND);
04523         ERROR2IF(pToolItem == NULL, NewHandle, "Unable to get tool item in DeactivateBrushDefAction::Init");
04524 
04525         FreeHandTool* pTool = (FreeHandTool*)pToolItem->m_pTool;
04526         ERROR2IF(pTool == NULL, NewHandle, "Unable to get tool in DeactivateBrushDefAction::Init");
04527         
04528         // get the infobar
04529         FreeHandInfoBarOp* pInfoBar = ((FreeHandTool*)pTool)->GetInfoBar();
04530         ERROR2IF(pInfoBar == NULL, NewHandle, "Unable to get InfoBar in DeactivateBrushDefAction::Init");
04531 
04532         // add to the freehand infobar
04533         pInfoBar->AddBrush(NewHandle);
04534     }
04535     return NewHandle;
04536 }
04537 
04538 
04539 /********************************************************************************************
04540 
04541 >   String_32 BrushComponent::GetUniqueName()
04542 
04543     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04544     Created:    13/12/99
04545     Inputs:     pName - the name that we wish to use, defaults to NULL in which
04546                 case we use the default name
04547     Returns:    A unique name which can be given to the brush
04548 
04549     Purpose:    When naming a new brush we want to give it the name supplied, 
04550                 however this may well be taken in which case we want to add
04551                 a number to the default name
04552 
04553 ********************************************************************************************/
04554 
04555 String_32 BrushComponent::GetUniqueName(String_32* pName)
04556 {
04557     // essentially what we're doing is going through all the brush definitions and
04558     // retrieving the portion of name that will could be equal to the default name.
04559     // We count the number of default names that we find and once we're finished 
04560     // we use this as the suffix for the new name
04561 
04562     // Get the default name from the resources
04563     String_32 DefaultName(_R(IDS_BRUSH_DEFAULT_NAME));
04564 
04565     if (pName == NULL)
04566         pName = &DefaultName;
04567     
04568     INT32 DefaultSize = pName->Length();
04569 
04570     BrushDefinition* pDef = NULL;
04571     String_32* pDefName = NULL;
04572     String_32 LeftMost;
04573     UINT32 Counter = 0;
04574     INT32 DefaultCounter = 0;
04575 
04576     // loop though the definitions
04577     while (Counter < m_Used)
04578     {
04579         pDef = FindBrushDefinition(Counter);
04580         if (pDef != NULL)
04581         {       
04582             pDefName = pDef->GetLineName();
04583             if (pDefName == NULL)
04584             {
04585                 ERROR3("Brush definition with no name in BrushComponent::GetUniqueName");
04586                 break;
04587             }
04588             // test to see if the leftmost portion of the name is the same as our default
04589             pDefName->Left(&LeftMost, DefaultSize);
04590             if (LeftMost.IsIdentical(*pName))
04591                 DefaultCounter++;
04592 
04593             LeftMost.Empty(); // wipe the default
04594         }
04595         Counter++;
04596     }
04597 
04598     String_32 UniqueName(*pName);
04599     
04600     // do we have to concatenate a number?
04601     if (DefaultCounter > 0)
04602     {
04603         String_32 Concat;
04604         Convert::LongToString(DefaultCounter, &Concat);
04605         UniqueName+=Concat;
04606     }
04607     return UniqueName;
04608 }
04609 
04610 
04611 
04612 
04613 /********************************************************************************************
04614 
04615 >   BOOL LineComponent::NameIsUnique(const String_32& NameString)
04616 
04617     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 
04618     Created:    3/7/2000
04619 
04620     Inputs:     NameString - the string to test
04621     Returns:    TRUE if none of the definitions in the component have this string as their name,
04622                 FALSE if one of them does
04623 
04624     Purpose:    To find out if someone has already gotten this name
04625 
04626 ********************************************************************************************/
04627 
04628 BOOL BrushComponent::NameIsUnique(const String_32& NameString)
04629 {
04630     if (NameString.IsEmpty())
04631         ERROR3("Empty string in BrushComponent::NameIsUnique");
04632     
04633     BOOL Unique = TRUE;
04634     UINT32 Counter = 0;
04635     String_32* pDefName = NULL;
04636     BrushDefinition* pDef = NULL;
04637     while (Counter < m_Used)
04638     {
04639         pDef = FindBrushDefinition(Counter);
04640         if (pDef != NULL)
04641         {
04642             pDefName = pDef->GetLineName();
04643             if( pDefName != NULL )
04644             {
04645                 if (NameString == *pDefName)
04646                 {
04647                     Unique = FALSE;
04648                     break;
04649                 }
04650             }
04651         }
04652         Counter++;
04653     }
04654     return Unique;
04655 
04656 }
04657 
04658 void BrushComponent::SetNewName(String_32 NewName)
04659 {
04660     m_NewName = NewName;
04661 }
04662 
04663 void BrushComponent::CancelNewBrush()
04664 {
04665     m_bCancelNewBrush = TRUE;
04666 }

Generated on Sat Nov 10 03:44:32 2007 for Camelot by  doxygen 1.4.4