opdrbrsh.cpp

Go to the documentation of this file.
00001 // $Id: opdrbrsh.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Implementation of OpDrawBrush
00100 
00101 #include "camtypes.h"
00102 #include "opdrbrsh.h"
00103 //#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 #include "pen.h"
00105 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "opfree.h"
00109 //#include "resource.h"
00110 #include "freehand.h"
00111 #include "csrstack.h"
00112 //#include "undoop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "combshps.h"
00114 //#include "rik.h"
00115 //#include "bubbleid.h"
00116 #include "ndbldpth.h"
00117 //#include "mario.h"
00118 #include "progress.h"
00119 //#include "range.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 //#include "grndbrsh.h"
00121 #include "objchge.h"
00122 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 #include "attrmap.h"
00124 #include "nodershp.h"
00125 #include "opbevel.h"
00126 #include "nodebev.h"
00127 //#include "markn.h"
00128 #include "blndtool.h"
00129 #include "brshattr.h"
00130 #include "brshcomp.h"
00131 #include "pathproc.h"
00132 #include "lineattr.h"
00133 #include "freehand.h"
00134 //#include "freehres.h"
00135 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00136 //#include "ccobject.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00137 #include "rsmooth.h"
00138 #include "camelot.h"
00139 #include "nodeshad.h"
00140 #include "nodecntr.h"
00141 #include "lineattr.h"
00142 #include "samplist.h"
00143 #include "linwthop.h"
00144 //#include "scrcamvw.h"
00145 #include "ophist.h"
00146 #include "ppbrush.h"
00147 
00148 #include "qualattr.h"
00149 
00150 // Declare the class
00151 CC_IMPLEMENT_DYNCREATE( OpDrawBrush, SelOperation );
00152 CC_IMPLEMENT_DYNCREATE( OpChangeBrush, SelOperation );
00153 CC_IMPLEMENT_DYNAMIC(ChangeBrushOpParam, OpParam);
00154 CC_IMPLEMENT_DYNCREATE(ChangeBrushAction, Action);
00155 CC_IMPLEMENT_DYNCREATE(RemoveTimeStampPointsAction, Action);
00156 CC_IMPLEMENT_DYNCREATE(AddTimeStampPointsAction, Action);
00157 CC_IMPLEMENT_DYNCREATE(UpdateBrushAction, Action);
00158 CC_IMPLEMENT_DYNCREATE(SetTimeStampUpdateTypeAction, Action);
00159 CC_IMPLEMENT_DYNCREATE(RemovePressurePointsAction, Action);
00160 CC_IMPLEMENT_DYNCREATE(AddPressurePointsAction, Action);
00161 
00162 #define DELPTR(p) if (p != NULL) { delete p; p = NULL; }
00163 #define SWAP(type,a,b) { type x=a; a=b; b=x; }
00164 
00165 // Declare smart memory handling in Debug builds
00166 #define new CAM_DEBUG_NEW
00167 
00168 const UINT32 PressureValsThreshold = 3; //basically the first 3 or so values coming out of the 
00169 
00170                                       // pressure pen are always zero, so we must ignore them
00171 
00172 
00173 
00174 /********************************************************************************************
00175 
00176 >   OpDrawBrush::OpDrawBrush()
00177 
00178     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00179     Created:    6/10/99
00180     Purpose:    Constructor.    
00181 ********************************************************************************************/
00182 
00183 OpDrawBrush::OpDrawBrush()
00184 {
00185     ResetMembers();
00186 }
00187 
00188 /********************************************************************************************
00189 
00190 >   OpDrawBrush::OpDrawBrush()
00191 
00192     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00193     Created:    6/10/99
00194     Purpose:    Constructor. This simply sets a few of the operation flags.
00195 
00196 ********************************************************************************************/
00197 
00198 OpDrawBrush::OpDrawBrush(FreeHandTool *pTool)
00199 {
00200     ResetMembers();
00201     if (pTool != NULL)
00202         m_pTool = pTool;
00203 }
00204 
00205 
00206 /********************************************************************************************
00207 
00208 >   OpDrawBrush::~OpDrawBrush()
00209 
00210     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00211     Created:    6/10/99
00212     Purpose:    destructor.
00213 
00214 ********************************************************************************************/
00215 
00216 OpDrawBrush::~OpDrawBrush()
00217 {
00218 //  if (m_pGRenderBrush != NULL)
00219 //      delete m_pGRenderBrush;
00220     if (m_pProcPathDistance != NULL)
00221         delete m_pProcPathDistance;
00222 
00223 
00224     if (m_pPathProcBrush != NULL)
00225         delete m_pPathProcBrush;
00226 
00227     if (m_pPressureList != NULL)
00228         delete m_pPressureList;
00229 
00230     if (m_pPointsCache != NULL)
00231         delete m_pPointsCache;
00232 
00233     if (m_pPressureSampler != NULL)
00234         delete m_pPressureSampler;
00235 }
00236 
00237 
00238 /********************************************************************************************
00239 
00240 >   void OpDrawBrush::ResetMembers()
00241 
00242     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00243     Created:    6/10/99
00244     Purpose:    Initialises all our member variables to something sensible
00245 
00246 ********************************************************************************************/
00247 
00248 void OpDrawBrush::ResetMembers()
00249 {
00250     // Set all our cursors to NULL to start with
00251     pFreeHandCursor = NULL;
00252     pJoinCursor = NULL;
00253     pStraightCursor = NULL;
00254     pRubOutCursor = NULL;
00255     pModifyCursor = NULL;
00256     
00257     // Set other default values
00258     TrackData = NULL;
00259     StartSpread = NULL;
00260     PreviousSpread = NULL;
00261     Smoothness = 512;
00262     LineSegmentCount = 0;
00263     CanLineJoin = FALSE;
00264     IsStraightLineMode = FALSE;
00265     AddPressureToPath = FALSE;
00266     FreeHandPressure = 0;
00267 
00268     // The paths that we are joined to, or NULL if we are joined to none
00269     pJoinInfo = NULL;
00270     StartPath = NULL;
00271     EndPath = NULL;
00272     CloseTo = 0;
00273     Mu = 0.0;
00274     IsEndNearEndpoint = FALSE;
00275     CurrentCursorID = 0;
00276 
00277     m_pGRenderBrush = NULL;
00278     m_pPathProcBrush = NULL;
00279 //#ifdef NEWFASTBRUSHES
00280     m_pBrushDefinition = NULL;
00281     mustClearStatusBar = TRUE;
00282     pApp = GetApplication ();
00283     ERROR3IF (!pApp, "Could not find the application!");
00284 //#endif
00285     m_pProcPathDistance = NULL;
00286     m_BrushScaling = 1.0;
00287 
00288 #ifdef OPBRUSHPOINTSCACHE
00289     m_pPointsCache = NULL;
00290 #endif
00291     
00292     m_pTimeStampList = NULL;
00293     m_TimeStamp      = 0;
00294     m_LastTimeStamp  = -1;
00295 
00296     m_pPressureList   = NULL;
00297 
00298     m_LastPathIndexRendered = 1;
00299 
00300     m_FirstSpacing = 25;
00301 
00302     m_pPressureSampler = NULL;
00303     m_NumPressureVals = 0;
00304 
00305 
00306 }
00307 
00308 /********************************************************************************************
00309 
00310 >   void OpDrawBrush::DoDrag( DocCoord Anchor, Spread *pSpread, INT32 Smooth, BrushHandle Handle, 
00311                             NodePath* pPath, Path* ToolPath, GRenderBitmap* pGRndBMP )
00312 
00313     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00314     Created:    6/10/99
00315     Inputs:     Anchor  - The position of the mouse at the start of the Drag
00316                 pSpread - The spread that the drag started on
00317                 Smooth  - Closeness of fit value
00318                 Handle - the handle of the brush we want to use
00319                 pFreeHandInfo - Pointer to the info about the Joining set up by the
00320                 freehand tool
00321                 ToolPath - The path to store the mouse tracking info in
00322                 pGRndBMP - pointer to the big bitmap used to store the view
00323                 
00324     Purpose:    Starts up the drag operation by storing all start positions and setting
00325                 up a Path to store the mouse movement in
00326 
00327 ********************************************************************************************/
00328 
00329 void OpDrawBrush::DoDrag(DocCoord Anchor, Spread *pSpread, INT32 Smooth, BrushHandle Handle,
00330                         FreeHandJoinInfo* pFreeHandInfo, Path* ToolPath,
00331                         GRenderBrush* pGRndRgn, ClickModifiers ClickMods)
00332 {
00333     TRACEUSER( "Diccon", _T("Drag started\n"));
00334     if (pSpread == NULL)
00335     {
00336         ERROR3("No spread");
00337         FailAndExecute();
00338         End();
00339         return;
00340     }
00341     if (ToolPath == NULL)
00342     {
00343         ERROR3("Tool path is NULL");
00344         FailAndExecute();
00345         End();
00346         return;
00347     }
00348 // WEBSTER - markn 25/4/97
00349 // No pen stuff required in Webster
00350 // Taken out by vector stroking code Neville 2/10/97
00351 #ifdef VECTOR_STROKING
00352     // Tell the pressure pen that we're starting a new stroke
00353     CCPen *pPen = pApp->GetPressurePen();
00354     if (pPen != NULL)
00355         pPen->StartStroke();
00356 #endif // VECTOR_STROKING
00357 
00358     // Snap the starting coord if we are not joining to something else
00359     if ((pFreeHandInfo==NULL) || (pFreeHandInfo->pJoinPath==NULL))
00360         DocView::SnapCurrent(pSpread, &Anchor, FALSE, TRUE);
00361 
00362     // Make a note of various starting conditions
00363     TrackData   = ToolPath;
00364     Smoothness  = Smooth;
00365     pJoinInfo   = pFreeHandInfo;
00366     StartPath   = pJoinInfo->pJoinPath;
00367     EndPath     = NULL;
00368 
00369     // Make a mental note of the start point
00370     StartPoint    = Anchor;
00371     StartSpread   = pSpread;
00372     PreviousSpread= pSpread;
00373     PreviousPoint = Anchor;
00374     LineSegmentCount = 0;
00375     IsStraightLineMode = FALSE;
00376     CanLineJoin = FALSE;
00377 
00378     // Prepare the Track data path and add in the initial click point to the path
00379     if (!PrepareTrackDataPath())
00380     {
00381         // We failed to get the memory to initialise the track data
00382         InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
00383         FailAndExecute();
00384         End();
00385         return;
00386     }
00387     
00388     // Create some cursors that I might need
00389     if (!LoadCursors())
00390     {
00391         // The cursors did not load, so fail?
00392         FailAndExecute();
00393         End();
00394         return;
00395     }
00396 
00397 
00398     // Push my new cursor onto the stack
00399     CurrentCursorID = CursorStack::GPush(pFreeHandCursor, TRUE);
00400     MyCurrentCursor = pFreeHandCursor;
00401 
00402     // Diccon new brush stuff
00403     TRACEUSER( "Diccon", _T("DRAG STARTED\n"));
00404     if (pGRndRgn == NULL)
00405     {
00406         ERROR3("No GRenderBrush");
00407         FailAndExecute();
00408         End();
00409         return;
00410     }
00411     else
00412         m_pGRenderBrush = pGRndRgn;
00413 
00414     // if we are joining a brush then make sure we know that handle
00415     if (pFreeHandInfo->m_BrushHandle != BrushHandle_NoBrush)
00416         Handle = pFreeHandInfo->m_BrushHandle;
00417 
00418     if (!InitialisePathProcessorBrush(Handle, pFreeHandInfo->BrushDistance))
00419     {
00420         FailAndExecute();
00421         End();
00422         return;
00423     }   
00424 
00425     // if out freehand info indicates that we are joining to an existing brush then 
00426     // copy out the data from that brush
00427     if (pFreeHandInfo->m_BrushHandle != BrushHandle_NoBrush && pFreeHandInfo->pAttrBrush != NULL)
00428     {   
00429 //      MILLIPOINT Spacing = 0;
00430         m_pPathProcBrush->GetSpacingAndScalingAtDistance(pFreeHandInfo->BrushDistance, &m_FirstSpacing, &m_BrushScaling);
00431     
00432         m_pPathProcBrush->CopyDataFromObject(&(pFreeHandInfo->m_BrushData));
00433         m_LastSpacing = m_pPathProcBrush->GetSpacing();
00434     
00435         // set the scaling, this can vary as we may be adding to a line
00436         // of any width
00437         m_BrushScaling = pFreeHandInfo->m_BrushData.m_BrushScaling; 
00438         
00439         m_pPathProcBrush->AdvanceBrushToDistance(pFreeHandInfo->BrushDistance);
00440 
00441         m_LastInkObjectRendered = m_pPathProcBrush->GetLastObject();
00442 
00443         // if we're overriding colours then tell the ppb what colour to use
00444         m_pPathProcBrush->SetUseLocalFillColour(pFreeHandInfo->UseLocalColour);
00445         m_pPathProcBrush->SetUseNamedColours(pFreeHandInfo->UseNamedColour);
00446         if (pFreeHandInfo->UseLocalColour || !pFreeHandInfo->UseNamedColour)
00447             m_pPathProcBrush->SetStrokeColour(pFreeHandInfo->StrokeColour);
00448 
00449     //  m_FirstSpacing = m_pPathProcBrush->GetLastSpacing() - pFreeHandInfo->FirstBrushSpacing;
00450 
00451     //  TRACEUSER( "Diccon", _T("JOINING EXISTING BRUSH\n"));
00452     }
00453 
00454     if (!InitialiseProcessPathDistance())
00455     {
00456         FailAndExecute();
00457         End();
00458         return;
00459     }
00460 
00461     if (!InitialisePressureSampler())
00462     {
00463         FailAndExecute();
00464         End();
00465         return;
00466     }
00467     if (AddPressureToPath == TRUE)
00468     {
00469     //  TRACEUSER( "Diccon", _T("Pressure = %d\n"), ClickMods.Pressure);
00470     //  m_pPressureSampler->CollectData(Anchor, ClickMods.Pressure);  //?? not sure this is right
00471     }
00472 
00473     if (m_pPathProcBrush != NULL)
00474     {
00475         m_NumInkObjects = m_pPathProcBrush->GetNumBrushObjects();
00476         m_BrushSpacing = m_pPathProcBrush->GetSpacing();
00477         m_pPathProcBrush->SetParentAttribute(pFreeHandInfo->pAttrBrush);
00478     }
00479     else
00480     {
00481         FailAndExecute();
00482         End();
00483         return;
00484     }
00485     if (m_NumInkObjects < 1)
00486     {
00487         ERROR3("No brush ink objects");
00488         FailAndExecute();
00489         End();
00490         return;
00491     }
00492 
00493     // if we are not timestamping then we want a regular point-at-distance map to
00494     // use as a cache, so long as we are not joining an existing brush
00495 #ifdef OPBRUSHPOINTSCACHE   
00496     if (m_TimeStamp <= 0 && pFreeHandInfo->m_BrushHandle == BrushHandle_NoBrush)
00497     {
00498         // allocate the map for caching
00499         m_pPointsCache = new PointsMap;
00500 
00501         //m_pPointsList = new List;
00502         // not a disaster if we don't get it
00503 //      if (m_pPointsCache != NULL)
00504 //          m_pPointsCache->InitHashTable(1277);    
00505 //      else
00506 //          ERROR3("Failed to allocate cache");
00507     }
00508 #endif
00509     // if we are timestamping then we want a list
00510     if (m_TimeStamp > 0)
00511     {
00512         if (!InitialiseTimeStampList())
00513         {
00514             // can't do anything if we don't get our cache
00515             FailAndExecute();
00516             End();
00517             return;
00518         }
00519     }
00520 
00521     // initialise needs to have correct start point
00522     m_StartPoint = Anchor;
00523     
00524     // set up the member variables
00525     m_LastPoint = Anchor;
00526     m_LastPointRendered = Anchor;
00527     m_LastDistanceRendered = 0;
00528     m_DistanceSinceLastObject = 0;
00529     m_LastSpacing = m_BrushSpacing;
00530     m_NumBrushObjects = 0;
00531 
00532     AddPointsToPath(Anchor, pSpread);
00533     m_bFirstPointRendered = FALSE;
00534 
00535     StartDrag( DRAGTYPE_NOSCROLL );
00536 
00537 //  TRACEUSER( "Diccon", _T("Drag initialised"));
00538 
00539 PORTNOTE("other", "Removed m_pRenderGBrush");
00540 #ifndef EXCLUDE_FROM_XARALX
00541 //#ifdef NEWFASTBRUSHES
00542     View*   pView = View::GetCurrent();
00543     CCamView* pCCamView = pView->GetConnectionToOilView();
00544     CDC* pDevContext = pCCamView->GetRenderDC();
00545     HDC DeviceHdc = pDevContext->GetSafeHdc();
00546 
00547     m_pGRenderBrush->SetView (pView);
00548     m_pGRenderBrush->SetCamView (pView->GetConnectionToOilView());
00549     m_pGRenderBrush->SetCDC (pCCamView->GetRenderDC());
00550     m_pGRenderBrush->SetHDC (pDevContext->GetSafeHdc());
00551 //#endif
00552 #endif
00553 }
00554 
00555 
00556 
00557 /********************************************************************************************
00558 
00559 >   void OpDrawBrush::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, 
00560                                   Spread *pSpread, BOOL bSolidDrag)
00561 
00562     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00563     Created:    7/10/99
00564     Inputs:     PointerPos - The current position of the mouse in Doc Coords
00565                 ClickMods - Which key modifiers are being pressed
00566                 pSpread - The spread that the mouse is moving over
00567     Purpose:    Handles the event of the mouse moving during a drag
00568     SeeAlso:    ClickModifiers
00569 
00570 ********************************************************************************************/
00571 
00572 void OpDrawBrush::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, 
00573                                   Spread *pSpread, BOOL bSolidDrag)
00574 {
00575     // Lets whip out the current pressure value
00576     if (AddPressureToPath)
00577         FreeHandPressure = ClickMods.Pressure;
00578 
00579     // If drag has moved onto a different spread, convert the coord to be relative to the
00580     // original spread.
00581     if (pSpread != StartSpread)
00582 #ifdef NEWFASTBRUSHES
00583         PointerPos = MakeRelativeToSpreadNoOverhead(StartSpread, pSpread, PointerPos);  // min variable allocation overhead version
00584 #else
00585         PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);    // min variable allocation overhead version
00586 #endif
00587 
00588     // I'm not allowing rubbing out or straightlines whilst drawing a brush
00589     ClickMods.Alternative1 = FALSE;
00590     ClickMods.Adjust = FALSE;
00591 
00592     // Change the Cursor to display the appropriate thing.
00593     SetCursorOnMove(ClickMods, StartSpread, &PointerPos);
00594 
00595     AddPointsToPath(PointerPos, StartSpread);
00596     // Set the last spread to something appropriate
00597     PreviousSpread = pSpread;
00598 
00599     //  brush specific code
00600     double Distance = (PointerPos.Distance(m_LastPoint));
00601     m_DistanceSinceLastObject += (MILLIPOINT)Distance;
00602         // cache the point for this brush object
00603     m_LastPoint = PointerPos;
00604     // pass the data to our pressure sampler
00605     if (m_pPressureSampler != NULL)
00606     {
00607         m_NumPressureVals++;
00608         if (m_NumPressureVals > PressureValsThreshold)
00609         {
00610             TRACEUSER( "Diccon", _T("Pressure = %d\n"), ClickMods.Pressure);
00611             
00612             if (!m_pPressureSampler->CollectData(PointerPos, FreeHandPressure))
00613             {
00614                 ERROR3("Error in Pressure sampler, aborting..");
00615                 FailAndExecute();
00616                 End();
00617                 return;
00618             }
00619         }
00620         else
00621             return;
00622         
00623     }
00624         // --- If the quality is set low enough, strokes are just rendered as centrelines
00625         // "low enough" is defined as the same point that Blends show their middle parts
00626         // BLOCK
00627         {
00628 PORTNOTE("other", "Removed m_pRenderGBrush");
00629 #ifndef EXCLUDE_FROM_XARALX
00630             if(m_pGRenderBrush != NULL)
00631             {
00632                 QualityAttribute *pQuality = (QualityAttribute *) m_pGRenderBrush->GetCurrentAttribute(ATTR_QUALITY);
00633                 if (pQuality != NULL && pQuality->QualityValue.GetBlendQuality() != Quality::FullBlend)
00634                 {
00635                     RenderRegion* pRegion = DocView::RenderOnTop(NULL, pSpread, UnclippedEOR );
00636                     while ( pRegion )
00637                     {
00638                         RenderLine(pRegion, TrackData, TrackData->GetNumCoords()-1, FALSE);
00639                         // get the next region to draw in
00640                         pRegion = DocView::GetNextOnTop(NULL);
00641                     }   
00642                     return;
00643                 }
00644             }
00645 #endif
00646         }
00647 
00648 //  if (pJoinInfo->BrushHandle != BrushHandle_NoBrush)
00649 //      RenderLine(m_pGRenderBrush, TrackData, TrackData->GetNumCoords()-1);
00650     // Render brush objects for the specified period
00651     RenderStepsForTime(50, pSpread);
00652 
00653     // if we are editing then render the path too
00654 /*  if (pJoinInfo->BrushHandle != BrushHandle_NoBrush)
00655     {
00656         RenderLine(NULL, pSpread, TrackData, TrackData->GetNumCoords() - 1);
00657         RenderLine(m_pGRenderBrush, TrackData, TrackData->GetNumCoords()-1);
00658     }*/
00659 }   
00660 
00661 
00662 
00663 /********************************************************************************************
00664 
00665 >   void OpDrawBrush::DragPointerIdle( DocCoord PointerPos, ClickModifiers ClickMods, 
00666                                   Spread *pSpread, BOOL bSolidDrag)
00667 
00668     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00669     Created:    7/10/99
00670     Inputs:     PointerPos - The current position of the mouse in Doc Coords
00671                 ClickMods - Which key modifiers are being pressed
00672                 pSpread - The spread that the mouse is moving over
00673     Purpose:    Handles the mouse idle events
00674     SeeAlso:    ClickModifiers
00675 
00676 ********************************************************************************************/
00677 
00678 void OpDrawBrush::DragPointerIdle(DocCoord PointerPos, ClickModifiers ClickMods, Spread* pSpread, BOOL bSolidDrag)
00679 {
00680     BOOL bAllowRender = TRUE;
00681     
00682     // --- If the quality is set low enough, strokes are just rendered as centrelines
00683     // "low enough" is defined as the same point that Blends show their middle parts
00684     // BLOCK
00685     {
00686 PORTNOTE("other", "Removed m_pRenderGBrush");
00687 #ifndef EXCLUDE_FROM_XARALX
00688         if(m_pGRenderBrush != NULL)
00689         {
00690             QualityAttribute *pQuality = (QualityAttribute *) m_pGRenderBrush->GetCurrentAttribute(ATTR_QUALITY);
00691             if (pQuality != NULL && pQuality->QualityValue.GetBlendQuality() != Quality::FullBlend)
00692             {
00693                 bAllowRender = FALSE;
00694                 // return;
00695             }
00696         }
00697 #endif
00698     }
00699 
00700     // because we are throwing away the first few pressure values we want to make sure we have 
00701     // got enough before we render here 
00702     if (AddPressureToPath)
00703     {
00704         if (m_NumPressureVals > PressureValsThreshold && bAllowRender)
00705             RenderStepsForTime(75, pSpread); // 75 is the time to render for in ms, as determined by trial and error
00706     }
00707     else
00708     {
00709         if(bAllowRender)
00710             RenderStepsForTime(75, pSpread);
00711     }
00712     
00713     //TRACEUSER( "Diccon", _T("Drag pointer idle\n"));  
00714 }
00715 
00716 /********************************************************************************************
00717 
00718 >   void OpDrawBrush::RenderStepsForTime(double TimeSlice, Spread* pSpread)
00719 
00720     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00721     Created:    20/10/99
00722     Inputs:     TimeSlice - the length of time to render for
00723                 pSpread - the spread to render on to
00724     Returns:    -
00725     Purpose:    Renders as many steps in the brush as possible in the time available.
00726                 The reason for having the code here rather than in the processor is twofold:
00727                 1) I feel the property of rendering for a certain timeslice is a property of
00728                 the Op rather than the PPB;
00729                 2) In order to make use of the caching ProcessPathDistance, which belongs
00730                 to the Op rather than the PPB.
00731 ********************************************************************************************/
00732 
00733 /* Notes: In case its not clear from the code what is happening here we go: the member variable
00734 m_DistanceSinceLastObject records how far the mouse has travelled since we last rendered an object.
00735 So long as this distance is greater than our spacing value then we wish to keep rendering points, and
00736 reducing m_DistanceSinceLastObject until it becomes less than our spacing value.
00737 */
00738 
00739 void OpDrawBrush::RenderStepsForTime(double TimeSlice, Spread* pSpread)
00740 {
00741     if ( (m_pProcPathDistance == NULL) || (m_pPathProcBrush == NULL)
00742         || (m_pGRenderBrush == NULL) || (TrackData == NULL))
00743     {
00744         ERROR3("One or more members are NULL");
00745         return;
00746     }
00747 
00748     MonotonicTime timer;
00749     
00750     // declare locals outside the loop
00751     DocCoord Point;
00752     double Angle;
00753     UINT32 Pressure = 0;
00754     CSampleItem TheItem;
00755     BrushPointInfo PathPoint;
00756 
00757     // records how far along the path we are
00758     MILLIPOINT DistanceToGetPoint = m_LastDistanceRendered;
00759 
00760     // spacing records the spacing between objects (duh)
00761     // this little hack is here to make sure our first object is a few millipoints in from the 
00762     // start of the path, otherwise we will always have a tangetial angle of zero
00763 
00764     MILLIPOINT Spacing = m_LastSpacing;
00765     if (!m_bFirstPointRendered)
00766     {
00767         Spacing = m_FirstSpacing;
00768         if (m_pPressureSampler != NULL)
00769         {
00770             if (m_pPressureSampler->GetAt(0, &TheItem))
00771                 Pressure = TheItem.m_Pressure;
00772             else
00773                 Pressure =127;
00774             m_pPathProcBrush->SetCurrentPressure(Pressure);
00775         }
00776     }
00777 
00778 
00779     BOOL Found;
00780     //m_BrushScaling = m_pPathProcBrush->GetLastScaling();
00781 #ifdef SCALESPACING
00782     double ActualSpacing = (double)Spacing * m_BrushScaling;
00783 #else
00784     double ActualSpacing = (double)Spacing * m_pPathProcBrush->GetBrushScaling();
00785 #endif
00786 //  if (TrackData->GetNumCoords() > 2)
00787 //      RenderLine(m_pGRenderBrush, TrackData, TrackData->GetNumCoords() - 1);
00788     UINT32 Dummy = 0;
00789     // render objects at m_BrushSpacing intervals starting at the last point rendered
00790     while (m_DistanceSinceLastObject >= (MILLIPOINT)ActualSpacing)
00791     {
00792         // the path processor needs to set up some variables to deal with offsets
00793         // before we come to actually render
00794         m_pPathProcBrush->SetNextOffsetType();
00795 
00796         //TRACEUSER( "Diccon", _T("Scaled Spacing = %f\n"), double(Spacing * m_BrushScaling));
00797         DistanceToGetPoint += (MILLIPOINT)ActualSpacing;
00798         
00799         // get the point from the nodebrushpath
00800         m_pProcPathDistance->GetCoordAndTangentWithCache(&Point, &Angle, &Found,
00801                                                         DistanceToGetPoint, TrackData, &Dummy);
00802         if (Found)
00803         {
00804             
00805             //TRACEUSER( "Diccon", _T("Point found at: %d, %d\n"), Point.x, Point.y);
00806             PathPoint.m_Point = Point;
00807             PathPoint.m_Tangent = Angle;
00808             PathPoint.m_Pressure = Dummy;
00809 
00810             // pass to the pathprocessor which does the work of rendering, but not if our object is zero-sized
00811 PORTNOTE("other", "Removed m_pRenderGBrush");
00812 #ifndef EXCLUDE_FROM_XARALX
00813             if (m_BrushScaling > 0)
00814             {
00815                 m_pPathProcBrush->RenderBrushAtPoint(Point, Angle, m_LastInkObjectRendered, m_NumBrushObjects,
00816                                                     m_pGRenderBrush, NULL, TRUE, m_pBrushDefinition);
00817             }
00818 #endif          
00819             // get the next pressure value
00820             if (m_pPressureSampler != NULL && m_bFirstPointRendered)
00821             {
00822                 m_pPressureSampler->SetSampleRateFromSpacing((MILLIPOINT)ActualSpacing);
00823                 
00824                 if (m_pPressureSampler->GetNext(&TheItem))
00825                     Pressure = TheItem.m_Pressure;
00826                 else
00827                     Pressure = 127;
00828                 m_pPathProcBrush->SetCurrentPressure(Pressure);
00829                 //TRACEUSER( "Diccon", _T("SETTING PRESSURE %d = %d\n"), m_NumBrushObjects, Pressure);
00830             }
00831 
00832 PORTNOTE("other", "Removed m_pRenderGBrush");
00833 #ifndef EXCLUDE_FROM_XARALX
00834             // get it to the screen ASAP
00835             m_pGRenderBrush->DrawToScreenNow();
00836 #endif
00837 
00838             m_DistanceSinceLastObject -= (MILLIPOINT)(ActualSpacing); //m_BrushSpacing;
00839             m_LastDistanceRendered = DistanceToGetPoint;
00840 
00841             // get the next spacing (spacing only changes once we have drawn an object)
00842             Spacing = m_pPathProcBrush->GetNextSpacing();
00843             m_BrushScaling = m_pPathProcBrush->GetLastScaling();
00844 #ifdef SCALESPACING
00845             ActualSpacing = Spacing * m_BrushScaling;
00846 #else
00847             ActualSpacing = (double)Spacing * m_pPathProcBrush->GetBrushScaling(); //m_BrushSpacing; //Spacing * m_BrushScaling;
00848 #endif
00849             // switch our alternating offset 
00850             m_pPathProcBrush->SwitchAlternateValue();
00851 
00852 #ifdef OPBRUSHPOINTSCACHE
00853             // stash this point in the cache
00854             if (m_pPointsCache != NULL)
00855                 (*m_pPointsCache)[DistanceToGetPoint]=PathPoint;
00856 #endif
00857          
00858             // get the next object in the sequence
00859             m_LastInkObjectRendered = m_pPathProcBrush->GetNextInkObject(m_LastInkObjectRendered,
00860                                                                      m_NumInkObjects);
00861 
00862             m_pPathProcBrush->DecideWhetherToUseActualScaling(m_LastInkObjectRendered);
00863             // increment our counter
00864             m_NumBrushObjects++;
00865             m_bFirstPointRendered = TRUE;
00866         //  TRACEUSER( "Diccon", _T("Pressure at end of loop = %d\n"), Pressure);
00867         }
00868 
00869         // if we hit the time constraint then just get out now
00870         if (timer.Elapsed(UINT32(TimeSlice * 1000.0)))
00871             break;
00872     }
00873 //  TRACEUSER( "Diccon", _T("Exit RenderStepsForTime\n"));
00874     // remember the spacing for next time
00875     m_LastSpacing = Spacing;
00876 }
00877 
00878 
00879 /********************************************************************************************
00880 
00881 >   void OpDrawBrush::RenderTimeStamp()
00882 
00883     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00884     Created:    20/10/99
00885     Inputs:     -
00886     Returns:    -
00887     Purpose:    To be used in timestamp mode, obviously.  This fn. determines whether or not 
00888                 enough time has elapsed for us to render a point.  If so we render a point
00889                 and cache it, updating the necessary members.
00890 ********************************************************************************************/
00891 
00892 void OpDrawBrush::RenderTimeStamp()
00893 {
00894     if (m_TimeStamp <=0)
00895     {
00896         ERROR3("Invalid timestamp value");
00897         return;
00898     }
00899 
00900     if (m_Timer.Elapsed((UINT32)(m_TimeStamp * 1000.0)))
00901     {   
00902         m_Timer.Sample();
00903         
00904         // find out how far along the path we are
00905         MILLIPOINT DistanceAlongPath = m_LastDistanceRendered + m_DistanceSinceLastObject;
00906         
00907         DocCoord Point;
00908         double Angle = 0;
00909         BOOL Found = FALSE;
00910         // get the point from the path
00911         m_pProcPathDistance->GetCoordAndTangentWithCache(&Point, &Angle, &Found,
00912                                                         DistanceAlongPath, TrackData);
00913     
00914         if (Found)
00915         {   
00916             TimeStampBrushPoint TSP(Point, Angle, DistanceAlongPath);
00917             
00918                 // get the next object in the sequence
00919         m_LastInkObjectRendered = m_pPathProcBrush->GetNextInkObject(m_LastInkObjectRendered,
00920                                                                      m_NumInkObjects);
00921 
00922 PORTNOTE("other", "Removed m_pRenderGBrush");
00923 #ifndef EXCLUDE_FROM_XARALX
00924             // pass to the pathprocessor which does the work of rendering
00925             if (m_pGRenderBrush != NULL)
00926             {
00927                 m_pPathProcBrush->RenderBrushAtPoint(Point, Angle, m_LastInkObjectRendered++, 1,
00928                                                 m_pGRenderBrush, NULL, TRUE);
00929                 // get it to the screen ASAP
00930                 m_pGRenderBrush->DrawToScreenNow();
00931                 TRACEUSER( "Diccon", _T("OpDrawBrush Rendered TimeStamp"));
00932             }
00933 #endif
00934             // update our member variables
00935             m_DistanceSinceLastObject = 0;
00936             m_LastDistanceRendered = DistanceAlongPath;
00937 
00938             // cache the point
00939             if (m_pTimeStampList != NULL)
00940                 m_pTimeStampList->push_back(TSP);
00941         }
00942     }
00943 }
00944 
00945 
00946 
00947 /********************************************************************************************
00948 
00949 >   void OpDrawBrush::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods,
00950                                Spread *pSpread, BOOL Success, BOOL bSolidDrag)
00951 
00952     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00953     Created:    7/10/99
00954     Inputs:     PointerPos - The position of the mouse at the end of the drag
00955                 ClickMods - the key modifiers being pressed
00956                 pSpread - The spread that the drag finished on
00957                 Success - TRUE if the drag was terminated properly, FALSE if it
00958                 was ended with the escape key being pressed
00959     Purpose:    Handles the drag finishing by rubbing out an EOR on the screen and
00960                 adding the path to the tree and building all the undo that will be
00961                 needed
00962     SeeAlso:    ClickModifiers
00963 
00964 ********************************************************************************************/
00965 
00966 void OpDrawBrush::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods,
00967                                Spread *pSpread, BOOL Success, BOOL bSolidDrag)
00968 {   
00969     TRACEUSER( "Diccon", _T("Drag finished\n"));
00970     // Erase the whole EORed line
00971     DocRect ClipRect(0,0,0,0);
00972     RenderDragBlobs(ClipRect, StartSpread, bSolidDrag);
00973     
00974     // Get rid of all the cursors
00975     RemoveCursors();
00976 
00977     // Put the hour glass up as we have to and end the drag
00978     //BeginSlowJob();
00979     String_32 ProgString = _T("Calculating brush, please wait..");
00980     Progress Hourglass(&ProgString, -1, FALSE);
00981 
00982     EndDrag();
00983     
00984     
00985     // Add the new path to the tree if it was valid
00986     BOOL Worked = FALSE;
00987     if (Success)
00988     {
00989         // were we in the middle of drawing a straight line
00990         if (IsStraightLineMode)
00991         {
00992             // we were so add it in to the track data
00993             AddStraightLine();
00994             PreviousPoint = StraightLinePos;
00995             IsStraightLineMode = FALSE;
00996         }
00997         BeginSlowJob(-1, TRUE, NULL);
00998         
00999         // invalidate the rect that we calculated (this may be different to the bounding 
01000         // rect of the node due to smoothing)
01001         DocRect BRect = m_pPathProcBrush->GetCachedRect();
01002 // Get rid of cached bitmaps here!
01003 Node* pANode = NULL;
01004 if (m_pPathProcBrush->GetParentAttribute())
01005 {
01006     pANode = m_pPathProcBrush->GetParentAttribute()->FindParent();
01007     if (pANode->IsBounded())
01008     {
01009         ((NodeRenderableBounded*)pANode)->ReleaseCached();
01010     }
01011 }
01012         DoInvalidateRegion(pSpread, BRect);
01013         
01014         // clean up some memory we used
01015         m_pPathProcBrush->CleanUpAfterRender();
01016 
01017         BrushDefinition* pDef = BrushComponent::FindBrushDefinition(m_pPathProcBrush->GetBrushDefinitionHandle());
01018         if (pDef)
01019             pDef->StopRender();
01020         else
01021             ERROR3("Unable to get brush definition in OpDrawBrush::DragFinished");
01022 
01023         // try and smooth the path and insert it into the tree
01024         Worked = CompleteOperation();
01025         EndSlowJob();   
01026     }
01027 // WEBSTER - markn 25/4/97
01028 // No pen stuff required in Webster
01029 // Taken out by vector stroking code Neville 2/10/97
01030 #ifdef VECTOR_STROKING
01031     // Inform the pressure pen that we've finished the stroke
01032     CCPen *pPen = pApp->GetPressurePen();
01033     if (pPen != NULL)
01034         pPen->EndStroke();
01035 #endif // VECTOR_STROKING
01036     
01037 
01038     if (m_pTool != NULL)
01039         m_pTool->BrushFinished();
01040 
01041     // point the pointer away from the render region (the tool still needs it so we don't delete)
01042     m_pGRenderBrush = NULL;
01043 
01044     // If the operation failed, then tidy up
01045     if (Worked==FALSE)
01046         FailAndExecute();
01047     else
01048     {
01049         // Update all the parents of the effected paths.
01050         ObjChangeFlags cFlags;
01051         ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01052         ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
01053         UpdateChangedNodes(&ObjChange);
01054     }
01055     // End the operation properly
01056     End();
01057 }
01058 
01059 
01060 /********************************************************************************************
01061 
01062 >   BOOL OpDrawBrush::ApplyAttributes(NodePath* NewPath, Document *pDocument)
01063 
01064     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01065     Created:    31/1/2000
01066     Inputs:     NewPath - The NodePath to apply the current attributes to
01067                 pDocument - the document this path will be placed into.
01068     Returns:    TRUE if it worked, FALSE if it did not
01069     Purpose:    Applies the current attributes to the Node passed in. It has to find the
01070                 current document to do this and will ENSURE if it fails to find one.
01071                 This overridden version also finds the newly applied brush attribute and 
01072                 gives it the cache of points that we have been recording
01073 
01074                 This fn. has changed slightly as we now have to comply with the "most recently
01075                 applied attributes" option.  In order to do this both the line width and the
01076                 brush attribute have to be applied via the attribute manager.
01077 
01078                 Andy Hills, 18-09-00
01079                 Note - I have temporarily reverted this function to the 24-08-00 version.
01080                 This fixes the problem where, if the above-mentioned option is disabled,
01081                 an access violation occurs.
01082 ********************************************************************************************/
01083 
01084 BOOL OpDrawBrush::ApplyAttributes(NodePath* pNewPath, Document *pDocument)
01085 {
01086     ERROR2IF(pNewPath == NULL, FALSE, "pNewNodePath is NULL in OpDrawBrush::ApplyAttributes");
01087     ERROR2IF(pDocument == NULL, FALSE, "pDocument is NULL in OpDrawBrush::ApplyAttributes");
01088     
01089     //ApplyRetroSmoother(pNewPath, 50);
01090     
01091     // Find the current document to get the current attributes from
01092     ENSURE(pDocument!=NULL, "Null Document while setting attributes for new NodePath");
01093     if (pDocument!=NULL)
01094     {   
01095         // we make out own attributes here
01096         AttrBrushType* pNewAttr = CreateNewAttribute();
01097         if (pNewAttr == NULL)
01098             return FALSE;
01099 #ifdef NEWFASTBRUSHES
01100         BrushAttrValue* pAttrVal = (BrushAttrValue*) pNewAttr->GetAttributeValue();
01101         pAttrVal->SetBoundsParent (pNewPath);
01102 #endif
01103         // now make the line the correct width, if someone has selected a line width then we will make it
01104         // that size, otherwise we will use the default provided by the brush
01105         MILLIPOINT LineWidth = GetCurrentLineWidthIfNotDefault();
01106         if (LineWidth == -1)
01107             LineWidth = pNewAttr->GetDefaultLineWidth(!AddPressureToPath);
01108     
01109     
01110         // Apply the current attributes to the path, changing the line width if necessary
01111         if (!pDocument->GetAttributeMgr().ApplyCurrentAttribsToNode((NodeRenderableInk*)pNewPath))
01112             ERROR3("Failed to apply current attributes in OpDrawBrush::ApplyAttributes");
01113         
01114         // change the line width value
01115         AttrLineWidth* pLineWidth = (AttrLineWidth*)pNewPath->FindFirstChild(CC_RUNTIME_CLASS(AttrLineWidth));
01116         if (pLineWidth != NULL)
01117             pLineWidth->Value.LineWidth = LineWidth;
01118         else
01119             ERROR3("Unable to find line width in OpDrawBrush::ApplyAttributes");
01120         
01121         // if the document inserted a brush then get rid of it
01122         Node* pDocBrush = pNewPath->FindFirstChild(CC_RUNTIME_CLASS(AttrBrushType));
01123         if (pDocBrush)
01124         {
01125             pDocBrush->CascadeDelete();
01126             delete pDocBrush;
01127             pDocBrush = NULL;
01128         }
01129 
01130 
01131         // apply our brush attribute here, in case the document already applied a default
01132         pNewPath->ApplyAttributeToObject(pNewAttr, FALSE);
01133         
01134         // tell it about the freehand tool
01135         pNewAttr->SetFreeHandTool(m_pTool);
01136 
01137         if (pNewAttr->GetBrushHandle() != BrushHandle_NoBrush)      
01138         {
01139                     
01140             #ifdef OPBRUSHPOINTSCACHE
01141             if (m_TimeStamp <= 0)
01142                 pNewAttr->SetCache(m_pPointsCache);
01143             
01144             // make sure we don't try to use the cache, the attribute is now responsible for
01145             // deleting it
01146             m_pPointsCache = NULL;
01147             #endif
01148             BrushAttrValue* pVal = (BrushAttrValue*)pNewAttr->GetAttributeValue();
01149             // if we're timestamping then set the timestamp cache instead
01150             if (m_TimeStamp > 0)
01151             {   
01152                 if (pVal != NULL)
01153                 {
01154                     pVal->SetTimeStampList(m_pTimeStampList);
01155                     pVal->CalculateProportionalDistances((MILLIPOINT)pNewPath->InkPath.GetPathLength());
01156                 }
01157             }
01158             // add the pressure cache, if we need to
01159             if (AddPressureToPath)
01160             {
01161                 //m_pPressureVals->SetSize(m_NumPressureVals, 1);
01162                 //m_pPressureVals->FreeExtra();
01163                 m_pPressureSampler->FinishSampling();
01164                 m_pPressureSampler->FreeExtra();
01165 
01166                 pNewAttr->SetPressureCache(m_pPressureSampler);
01167                 // set our pointer to null so we don't end up deleting it
01168                 m_pPressureSampler = NULL;
01169                 
01170                 // ask the attribute to calculate the proportional distances
01171                 //if (pVal != NULL)
01172                 //  pVal->CalculatePressureArrayProportions((MILLIPOINT)pNewPath->InkPath.GetPathLength());
01173             }
01174         }
01175 
01176         return TRUE;
01177     }
01178 
01179     // We failed to apply the attributes, so fail
01180     return FALSE;
01181 }
01182 
01183 
01184 /********************************************************************************************
01185 
01186 >   BOOL OpDrawBrush::ApplyRetroSmoother(NodePath* NewPath, Spread* pSpread, double SmoothAmount)
01187 
01188     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01189     Created:    31/1/2000
01190     Inputs:     NewPath - The NodePath that we have created
01191                 SmoothAmount - the amount that we wish to smooth (0 -100)
01192     Returns:    TRUE if it worked, FALSE if it did not
01193     Purpose:    Initialises the RetroSmoother object and uses it to smooth the nodepath we have
01194                 created.  The reason for using this smoother rather than the FreeHand smoother
01195                 is that it does not seem to change the shape of the path in a visible way.
01196                 It is useful to apply this because otherwise the paths that we draw have too
01197                 many control points which can obscure the brush objects.
01198 
01199 ********************************************************************************************/
01200 
01201 BOOL OpDrawBrush::ApplyRetroSmoother(NodePath* pNodePath, double SmoothAmount)
01202 {
01203     ERROR2IF(pNodePath == NULL, FALSE, "NodePath is NULL in OpDrawBrush::ApplyRetroSmoother");
01204     
01205     // make a smoothing object
01206     RetroSmooth Smoother;
01207 
01208     if (!Smoother.Initialise())
01209         return FALSE;
01210 
01211     // tell the smoother we don't want EOR rendering
01212     Smoother.SetRenderFlag(FALSE);
01213 
01214     // we need to set all our path elements selected for the smoother
01215     pNodePath->InkPath.SetAllSubSelection();
01216 
01217     // we need the spread for the smoothing operation
01218     Spread* pSpread = Document::GetSelectedSpread();
01219     if (pSpread == NULL)
01220     {
01221         ERROR3("Spread is NULL in OpDrawBrush::ApplyRetroSmoother");
01222         return FALSE;
01223     }
01224 
01225     Smoother.Changing(pNodePath, pSpread, SmoothAmount);
01226     Smoother.FinishedNoUndo(pNodePath);
01227 
01228     // unselect our path elements
01229     pNodePath->InkPath.ClearSubSelection();
01230 
01231     return TRUE;
01232 }
01233 
01234 
01235 
01236 /********************************************************************************************
01237 
01238 >   AttrBrushType* OpDrawBrush::CreateNewAttribute()
01239 
01240     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01241     Created:    6/10/99
01242     Returns:    TRUE if all went OK, False otherwise
01243     Purpose:    Adds the operation to the list of all known operations
01244 
01245 ********************************************************************************************/
01246 
01247 AttrBrushType* OpDrawBrush::CreateNewAttribute()
01248 {
01249         
01250     AttrBrushType* pNewAttr = new AttrBrushType;
01251     if (pNewAttr == NULL)
01252     {
01253         ERROR3("Couldn't make attribute node");
01254         return NULL;
01255     }
01256     
01257     BrushAttrValue* pVal = (BrushAttrValue*)pNewAttr->GetAttributeValue();
01258     if (pVal == NULL)
01259     {
01260         ERROR3("No attribute value");
01261         return NULL;
01262     }
01263 
01264     if (m_pPathProcBrush == NULL)
01265     {
01266         ERROR3("Path Processor Brush is NULL already");
01267         return NULL;
01268     }
01269     pVal->SetPathProcessor(m_pPathProcBrush);
01270 
01271     m_pPathProcBrush->SetParentAttribute(pNewAttr);
01272 
01273     // make sure our processor has all the correct data
01274     Document* pDoc = Document::GetCurrent();
01275     ERROR2IF(pDoc == NULL, pNewAttr, "No document in OpDrawBrush::CreateNewAttribute");
01276     BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent));
01277     ERROR2IF(pBrushComp == NULL, pNewAttr, "No brush component in OpDrawBrush::CreateNewAttribute");
01278     BrushDefinition* pBrushDef = pBrushComp->FindBrushDefinition(m_pPathProcBrush->GetBrushDefinitionHandle());
01279     ERROR2IF(pBrushDef == NULL, pNewAttr, "Unable to retrieve brush definition, invalid handle");
01280     
01281     // copy the data from the definition
01282     pBrushDef->CopyDataToProcessor(m_pPathProcBrush);
01283 
01284     // scale to the appropriate line width (or not)
01285     
01286     MILLIPOINT LineWidth = GetCurrentLineWidthIfNotDefault();
01287     if (LineWidth != -1)
01288     {
01289         m_pPathProcBrush->ScaleToValue(LineWidth, !AddPressureToPath);
01290     }
01291     else
01292     {
01293         MILLIPOINT Size = pBrushDef->GetDefaultLineWidth(!AddPressureToPath);
01294         m_pPathProcBrush->ScaleToValue(Size, !AddPressureToPath);
01295     }
01296 
01297     // make sure we don't delete it now
01298     m_pPathProcBrush = NULL;
01299     return pNewAttr;
01300 }
01301 
01302 
01303 /********************************************************************************************
01304 
01305 >   BOOL OpDrawBrush::EditBrushLists(NodePath* pNewPath, INT32 FirstChangedIndex,
01306                                         INT32 NumElements)
01307 
01308     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01309     Created:    19/3/2000
01310     Inputs:     pNewPath - The New curve that has just been draw
01311                 FirstChangedIndex - The first coord in the path that is to be replaced
01312                 NumElements - The number of elements in the path that need replacing
01313     Returns:    TRUE if it worked, FALSE if not
01314     Purpose:    When we are editing a brush that contains either timestamping or pressure data 
01315                 and we are editing using a brush we will have generated our own list of TS or 
01316                 pressure info that we need to insert into the existing list.  This fn. manages
01317                 the insertion of these lists and any others that might arise.
01318 
01319 ********************************************************************************************/
01320 
01321 BOOL OpDrawBrush::EditBrushLists(NodePath* pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
01322 {
01323     ERROR2IF(pNewPath == NULL, FALSE, "pNewPath is NULL in OpDrawBrush::EditBrushLists");
01324 
01325     BOOL ok = TRUE;
01326     // if we have a timestamp list then attempt to insert it
01327     if (m_pTimeStampList != NULL)
01328         ok = EditTimeStampList(pNewPath, FirstChangedIndex, NumElements);
01329     // edit the pressure list (if there is one)
01330     if (ok)
01331         ok = EditPressureList(pNewPath, FirstChangedIndex, NumElements);
01332 
01333     return ok;
01334 }
01335 
01336 /********************************************************************************************
01337 
01338 >   BOOL OpDrawBrush::EditTimeStampList(NodePath* pNewPath, INT32 FirstChangedIndex,
01339                                         INT32 NumElements)
01340 
01341     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01342     Created:    19/3/2000
01343     Inputs:     pNewPath - The New curve that has just been draw
01344                 FirstChangedIndex - The first coord in the path that is to be replaced
01345                 NumElements - The number of elements in the path that need replacing
01346     Returns:    TRUE if it worked, FALSE if not
01347     Purpose:    When a path is edited that has a timestamping brush applied to it we those 
01348                 points are stored in a list that is generated when the path is drawn.  If we 
01349                 subsequently want to edit that path we have to insert or remove points from 
01350                 that list.  This function works out what points should be inserted or removed,
01351                 and performs that action on the applied brush.
01352                 This is made slightly easier
01353 
01354 ********************************************************************************************/
01355 
01356 BOOL OpDrawBrush::EditTimeStampList(NodePath* pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
01357 {
01358     ERROR2IF(pNewPath == NULL, FALSE, "pNewPath is NULL in OpDrawBrush::EditTimeStampingBrush");
01359 
01360     // if we're not timestamping then just return now
01361     if (m_pTimeStampList == NULL)
01362         return TRUE;
01363 
01364     /* First up, find the nearest applied brush attribute. If there isn't one or
01365     it is not timestamping then we don't have to bother with all this */
01366     AttrBrushType* pAttrBrush = NULL;
01367 
01368     pAttrBrush = EndPath->GetAppliedBrushAttribute();
01369     if (pAttrBrush == NULL)
01370         return TRUE;
01371 
01372     // if we are attempting to edit an existing brush that does not use the timestamping 
01373     // system then also give up
01374     if (!pAttrBrush->IsTimeStamping())
01375         return TRUE;
01376     
01377     // most of the action takes place in the attribute value so get that also
01378     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
01379     if (pVal == NULL)
01380         return TRUE;
01381 
01382     /* next, record the following distances:
01383     - original path length;
01384     - distance to first changed point;
01385     - distance to last changed point;
01386     */
01387 
01388 //  double OriginalLength = EndPath->InkPath.GetPathLength();
01389     MILLIPOINT DistToFirstPoint = -1;
01390     MILLIPOINT DistToLastPoint = -1;
01391     DocCoord* pCoords = EndPath->InkPath.GetCoordArray();
01392 
01393     DocCoord FirstChangedPoint;
01394     DocCoord LastChangedPoint;
01395 
01396     if (pCoords == NULL)
01397         return FALSE;
01398     if (FirstChangedIndex + NumElements > EndPath->InkPath.GetNumCoords())
01399     {
01400         ERROR3("Illegal number of coordinates");
01401         return FALSE;
01402     }
01403 
01404     // get the coordinates from the array
01405     FirstChangedPoint = pCoords[FirstChangedIndex];
01406     LastChangedPoint  =  pCoords[FirstChangedIndex + NumElements];
01407 
01408     EndPath->InkPath.GetDistanceToPoint(FirstChangedPoint, &DistToFirstPoint);
01409     EndPath->InkPath.GetDistanceToPoint(LastChangedPoint, &DistToLastPoint);
01410 
01411 
01412     /* now get the timestamping points list and ask the attribute to clear all the points
01413     between the edited distances*/
01414     
01415     // first make a removepoints action
01416     RemoveTimeStampPointsAction* pAction; 
01417     
01418     if (RemoveTimeStampPointsAction::Init(this, &UndoActions, pAttrBrush, DistToFirstPoint, DistToLastPoint, NULL, &pAction) == AC_FAIL)
01419         return FALSE;
01420 
01421     // now insert our new points into the attribute
01422     AddTimeStampPointsAction* pAddAction;
01423     
01424     // find out the distance of the new points to be inserted
01425     TimeStampBrushPoint StartPoint = m_pTimeStampList->front();
01426     TimeStampBrushPoint EndPoint   = m_pTimeStampList->back();
01427 
01428     INT32 NewPointsDistance = EndPoint.m_Distance - StartPoint.m_Distance;
01429 
01430     if (AddTimeStampPointsAction::Init(this, &UndoActions, pAttrBrush, m_pTimeStampList, DistToFirstPoint, DistToFirstPoint + NewPointsDistance, 0, &pAddAction) == AC_FAIL)
01431         return FALSE;
01432 
01433     // invalidate the whole thing3
01434     if (!DoInvalidateNodeRegion(EndPath, TRUE))
01435         return FALSE;       
01436 
01437     return TRUE;
01438 }
01439 
01440 
01441 /********************************************************************************************
01442 
01443 >   BOOL OpDrawBrush::EditPressureList(NodePath* pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
01444 
01445     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01446     Created:    19/3/2000
01447     Inputs:     pNewPath - The New curve that has just been draw
01448                 FirstChangedIndex - The first coord in the path that is to be replaced
01449                 NumElements - The number of elements in the path that need replacing
01450     Returns:    TRUE if it worked, FALSE if not
01451     Purpose:    
01452 
01453 ********************************************************************************************/
01454 
01455 BOOL OpDrawBrush::EditPressureList(NodePath* pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
01456 {
01457     ERROR2IF(pNewPath == NULL, FALSE, "pNewPath is NULL in OpDrawBrush::EditPressureList");
01458 
01459         /* First up, find the nearest applied brush attribute. If there isn't one or
01460     it has no pressure list then we don't have to bother with all this */
01461     AttrBrushType* pAttrBrush = NULL;
01462 
01463     pAttrBrush = EndPath->GetAppliedBrushAttribute();
01464     if (pAttrBrush == NULL)
01465         return TRUE;
01466 
01467     // if we are attempting to edit an existing brush that does not have an existing pressure
01468     // cache then leave now
01469     if (!pAttrBrush->ContainsPressureCache())
01470         return TRUE;
01471     
01472     // most of the action takes place in the attribute value so get that also
01473     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
01474     if (pVal == NULL)
01475         return TRUE;
01476 
01477     /* next, record the following distances:
01478     - original path length;
01479     - distance to first changed point;
01480     - distance to last changed point;
01481     */
01482 
01483 //  double OriginalLength = EndPath->InkPath.GetPathLength();
01484     MILLIPOINT DistToFirstPoint = -1;
01485     MILLIPOINT DistToLastPoint = -1;
01486     DocCoord* pCoords = EndPath->InkPath.GetCoordArray();
01487 
01488     DocCoord FirstChangedPoint;
01489     DocCoord LastChangedPoint;
01490 
01491     if (pCoords == NULL)
01492         return FALSE;
01493     if (FirstChangedIndex + NumElements > EndPath->InkPath.GetNumCoords())
01494     {
01495         ERROR3("Illegal number of coordinates");
01496         return FALSE;
01497     }
01498 
01499     // get the coordinates from the array
01500     FirstChangedPoint = pCoords[FirstChangedIndex];
01501     LastChangedPoint  =  pCoords[FirstChangedIndex + NumElements];
01502 
01503     EndPath->InkPath.GetDistanceToPoint(FirstChangedPoint, &DistToFirstPoint);
01504     EndPath->InkPath.GetDistanceToPoint(LastChangedPoint, &DistToLastPoint);
01505 
01506     // Now find the indices into the pressure list that correspond to those distances
01507     INT32 StartPressureIndex = pVal->GetPressureListIndexAtDistance(DistToFirstPoint);
01508     if (StartPressureIndex == -1)
01509     {
01510         ERROR3("StartPressureIndex is -1 in OpDrawBrush::EditPressureList");
01511         return FALSE;
01512     }
01513     
01514     INT32 EndPressureIndex = pVal->GetPressureListIndexAtDistance(DistToLastPoint);
01515     if (EndPressureIndex == -1 || EndPressureIndex <= StartPressureIndex)
01516     {
01517         ERROR3("EndPressureIndex is invalid in OpDrawBrush::EditPressureList");
01518         return FALSE;
01519     }
01520     UINT32 NumObjects = EndPressureIndex - StartPressureIndex;
01521 //  MILLIPOINT Spacing = pAttrBrush->GetSpacing();
01522     UINT32 NumIndexes = 0; //Spacing / MIN_BRUSH_SPACING;
01523     StartPressureIndex -= NumIndexes;
01524     if (StartPressureIndex < 0)
01525         StartPressureIndex = 0;
01526     
01527 //  if (m_pPressureList == NULL)
01528 //      m_pPressureList = GeneratePressureList(pAttrBrush, StartPressureIndex, EndPressureIndex, 
01529 //                                              (MILLIPOINT)pNewPath->InkPath.GetPathLength()); 
01530 
01531 //  if (m_pPressureList == NULL)  // did it fail, of so we must quit
01532 //      return FALSE;
01533     /* now get the pressure points list and ask the attribute to clear all the points
01534     between the edited distances*/
01535     pAttrBrush->ClearCachedRect();
01536     DocRect Rect = pAttrBrush->GetAttrBoundingRect(EndPath);
01537     Spread* pSpread = Document::GetSelectedSpread();
01538 
01539     if (!DoInvalidateRegion(pSpread, Rect))
01540         return FALSE;
01541     // Invalidate it as it was
01542     if (!DoInvalidateNodeRegion(EndPath, TRUE))
01543         return FALSE;       
01544 
01545     // now make a removepoints action
01546     RemovePressurePointsAction* pAction;
01547 
01548     if (m_pPressureSampler)
01549     {
01550         // only remove items if m_pPressureSampler is non-NULL!
01551         if (RemovePressurePointsAction::Init(this, &UndoActions, pAttrBrush, (UINT32)StartPressureIndex, NumObjects, NULL, &pAction) == AC_FAIL)
01552             return FALSE;
01553     }
01554 
01555     // now insert our new points into the attribute
01556     AddPressurePointsAction* pAddAction;
01557 
01558     if (m_pPressureSampler)
01559     {
01560         // find out how many points we're inserting
01561         UINT32 NumAddPoints = m_pPressureSampler->GetNumItems();
01562         
01563         if (AddPressurePointsAction::Init(this, &UndoActions, pAttrBrush, m_pPressureSampler, (UINT32)StartPressureIndex, NumAddPoints,  &pAddAction) == AC_FAIL)
01564             return FALSE;
01565     }
01566     else
01567     {
01568         // YUCK, this means that somebodies trying to 'glue' a non-pressure sensititive path in with the pressure
01569         // sensitive one ....
01570 
01571         // I think the most sensible thing to do is just to leave current pressure data intact.  Otherwise we get
01572         // bogged down in bodging default pressure values (which might not be what the user wants/go wrong), and trouble
01573         // with undo/redo by replacing these values on the fly.
01574     }
01575 
01576     m_pPressureSampler = NULL; // otherwise we end up deleting it whilst we still need it
01577     // invalidate the whole thing
01578     pAttrBrush->ClearCachedRect();
01579     Rect = pAttrBrush->GetAttrBoundingRect(EndPath);
01580     EndPath->ReleaseCached();
01581     
01582     if (!DoInvalidateRegion(pSpread, Rect))
01583         return FALSE;
01584     
01585     return TRUE;
01586 }
01587 
01588 /********************************************************************************************
01589 
01590 >   BOOL OpDrawBrush::SimpleJoin(NodePath* pInsertedNode, Path* pNewPath)
01591 
01592     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01593     Created:    20/3/2000
01594     Inputs:     pInsertedNode - the node that we have just inserted
01595                 pPath - the new section of path that we have just drawn
01596     Returns:    TRUE if it worked, FALSE if it failed
01597     Purpose:    Joins a Simple path with the new freehand path and builds all the undo that
01598                 is needed in the process.
01599 
01600                 This version also incorporates code to insert timestamping or pressure data if
01601                 we are editing such a brush
01602 
01603 ********************************************************************************************/
01604 
01605 BOOL OpDrawBrush::SimpleJoinBrush(NodePath* pInsertedNode, Path* pNewPath)
01606 {
01607     if (pInsertedNode == NULL || pNewPath == NULL)
01608     {
01609         ERROR3("Null inputs to OpDrawBrush::SimpleJoinBrush");
01610         return FALSE;
01611     }
01612     
01613     // first check to see if the edited path has a brush applied to it,
01614     // if it doesn't then we'll leave
01615     NodeAttribute* pAttr;
01616     AttrBrushType* pAttrBrush;
01617     pInsertedNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr);
01618     if (pAttr == NULL)
01619         return TRUE;
01620 
01621     pAttrBrush = (AttrBrushType*)pAttr;
01622     // if our brush has a 'no brush' handle then likewise
01623     if (pAttrBrush->GetBrushHandle() == BrushHandle_NoBrush)
01624         return TRUE;
01625 
01626     // if our brush is not either timestamping or has a pressure list then we will leave aswell
01627     CDistanceSampler* pPressData = pAttrBrush->GetPressureCache();
01628     if (pPressData == NULL)
01629         return TRUE;
01630 
01631     // Do we have a pressure cache??
01632     if (m_pPressureSampler == NULL)
01633         return TRUE;
01634 
01635     // find out what type of join we have 
01636     SimpleJoinType JoinType = GetSimpleJoinType(pNewPath, &(pInsertedNode->InkPath));
01637     if (JoinType == JOINTYPE_NONE)
01638     {
01639         ERROR3("No join type in OpDrawBrush::SimpleJoinBrush");
01640         return TRUE;
01641     }
01642 
01643     // we need to know the distance along the original path where we want to insert the
01644     // new points.  As this is a simple join it will either be at the beginning or the end.
01645     // we also need to know the distance to the end of the new points, as this is required
01646     // for the undo.
01647     MILLIPOINT NewPathLength = (MILLIPOINT)pNewPath->GetPathLength();
01648     MILLIPOINT OldPathLength = -1;
01649     if (StartPath != NULL)
01650     {
01651         OldPathLength = (MILLIPOINT)StartPath->InkPath.GetPathLength(); 
01652     }
01653     else 
01654     {
01655         if (EndPath != NULL)
01656             OldPathLength = (MILLIPOINT)EndPath->InkPath.GetPathLength();
01657     }
01658 
01659     MILLIPOINT InsertDistance = -1;
01660     MILLIPOINT EndInsertDistance = -1;
01661     INT32 StartIndex = 0; //where we will begin our insert
01662     
01663     // according to the type of join we will want to insert our new data at the beginning or the
01664     // end, we may also want to reverse it
01665     switch (JoinType)
01666     {
01667         case JOINTYPE_NEWSTART_TO_OLDSTART:
01668             InsertDistance = 0;
01669             EndInsertDistance = NewPathLength;
01670             StartIndex = 0; 
01671             // in this instance we reversed the new path section so also reverse the pressure data
01672             m_pPressureSampler->ReverseData();
01673             break;
01674         case JOINTYPE_NEWSTART_TO_OLDEND:
01675             InsertDistance = OldPathLength;
01676             EndInsertDistance = OldPathLength + NewPathLength;
01677             StartIndex = pPressData->GetInternalIndexFromDistance(OldPathLength);
01678             if (StartIndex==-1) StartIndex = pPressData->GetNumItems();
01679             break;
01680         case JOINTYPE_NEWEND_TO_OLDSTART:  
01681             InsertDistance = 0;
01682             EndInsertDistance = NewPathLength;
01683             StartIndex = 0; 
01684             break;
01685         case JOINTYPE_NEWEND_TO_OLDEND:
01686             InsertDistance = OldPathLength;
01687             EndInsertDistance = OldPathLength + NewPathLength;
01688             StartIndex = pPressData->GetInternalIndexFromDistance(OldPathLength);   
01689             if (StartIndex==-1) StartIndex = pPressData->GetNumItems();
01690             m_pPressureSampler->ReverseData();
01691             break;
01692         default:
01693             ERROR3("Unknown join type in OpDrawBrush::SimpleJoinBrush");
01694             return FALSE;
01695     }
01696 
01697     // make the action to insert the pressure list
01698     if (m_pPressureSampler != NULL)
01699     {
01700         AddPressurePointsAction* pAction;
01701         UINT32 NumPoints = m_pPressureSampler->GetNumItems();
01702 
01703         if (AddPressurePointsAction::Init(this, &UndoActions, pAttrBrush, m_pPressureSampler, 
01704                                         StartIndex, NumPoints, &pAction) == AC_FAIL)
01705             return FALSE;
01706         m_pPressureSampler = NULL;  // so we don't delete it 
01707     }
01708 
01709     return TRUE;
01710 }
01711 
01712 
01713 /********************************************************************************************
01714 
01715 >   BOOL OpDrawBrush::RetroSmoothBrush(NodePath* pNewNodePath)
01716 
01717     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01718     Created:    19/3/2000
01719     Inputs:     pNewPath - The New curve that has just been drawn
01720             
01721     Returns:    TRUE 
01722     Purpose:    As above, the base class version does nothing
01723 
01724 ********************************************************************************************/
01725 
01726 BOOL OpDrawBrush::RetroSmoothBrush(NodePath* pNewNodePath)
01727 {
01728     return ApplyRetroSmoother(pNewNodePath, 85);
01729 }
01730 
01731 
01732 /********************************************************************************************
01733 
01734 >   BOOL OpDrawBrush::ReverseBrushPressure()
01735 
01736     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01737     Created:    20/3/2000
01738     Inputs: 
01739     Returns:    TRUE if it worked, FALSE if it failed, or if we aren't using pressure
01740     Purpose:    Calls the attribute function to reverse our pressure list
01741 
01742 ********************************************************************************************/
01743 
01744 BOOL OpDrawBrush::ReverseBrushPressure()
01745 {
01746     if (m_pPressureSampler == NULL)
01747         return FALSE;
01748 
01749     return m_pPressureSampler->ReverseData();
01750 }
01751 
01752 
01753 /********************************************************************************************
01754 
01755 >   CDistanceSampler* OpDrawBrush::GeneratePressureList(AttrBrushType* pAttrBrush, MILLIPOINT Start,
01756                                                     MILLIPOINT End, MILLIPOINT NewPathLength)
01757 
01758     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01759     Created:    20/3/2000
01760     Inputs:     pAttrBrush - the brush that we are joining to 
01761                 Start      - the distance along the original path where we want to start the insert, 
01762                              set this to -1 to indicate we are inserting at the beginning of the path
01763 
01764                 End        - the distance along the original path where we wish to end the insert, 
01765                             set this to -1 to indicate that we are inserting at the end of the path
01766 
01767                 NewPathLength - the length of the path that we wish to insert
01768             
01769     Returns:    a newly generated pressure sampler, complete with values (or NULL if we fail)
01770     Purpose:    This function deals with the case when we wish to edit a brush with pressure data
01771                 but we do not generate a pressure list during the edit for some reason.
01772                 In this case we must create a new pressure list and fill it with values based upon
01773                 the values in the existing brush pressure list
01774 
01775 ********************************************************************************************/
01776 
01777 CDistanceSampler* OpDrawBrush::GeneratePressureData(AttrBrushType* pAttrBrush, MILLIPOINT Start,
01778                                                      MILLIPOINT End, MILLIPOINT NewPathLength)
01779 {
01780     if (pAttrBrush == NULL)
01781     {
01782         ERROR3("Entry pointer is NULL in OpDrawBrush::GeneratePressureList");
01783         return NULL;
01784     }
01785     if (NewPathLength < 0 )
01786     {
01787         ERROR3("Negative path length in OpDrawBrush::GeneratePressureList");
01788         return NULL;
01789     }
01790     
01791     // just make sure we actually have a pressure list
01792     CDistanceSampler* pSampler = pAttrBrush->GetPressureCache();
01793     if (pSampler == NULL)
01794     {
01795         ERROR3("Why are you trying to do a pressure edit when this brush doesn't use pressure!??");
01796         return NULL;
01797     }
01798 
01799     /* there are two possibilities here: 
01800     1) we are inserting in the middle, in which case get the two insert values and interpolate, or
01801     2) we are inserting at the beginning or end, in which case just repeat the first/last value
01802     */
01803     // get the pressure values at StartIndex and EndIndex
01804     INT32 StartIndex = -1;
01805     INT32 EndIndex   = -1;
01806     
01807     // case 1
01808     if (Start != -1 && End != -1)
01809     {
01810         StartIndex = pSampler->GetInternalIndexFromDistance(Start);
01811         EndIndex = pSampler->GetInternalIndexFromDistance(End);
01812     }
01813 
01814     // case 2
01815     else if (Start == -1)
01816             StartIndex = EndIndex = 0;
01817     else if (End == -1)
01818             StartIndex = EndIndex = pSampler->GetInternalIndexFromDistance(Start);
01819 
01820     // just make sure we got valid indexes
01821     if (StartIndex == -1 || EndIndex == -1)
01822     {
01823         ERROR3("Start or end index off the end of the array in OpDrawBrush::GeneratePressureData");
01824         return NULL;
01825     }
01826         
01827     // we are using internal indexes so set the sample rate to 1.0
01828     pSampler->SetRetrievalSampleRate(1.0);
01829 
01830     // get the starting pressure, make it a double as we're going to be doing lots of fp ops.
01831     CSampleItem StartItem;
01832     BOOL ok = pSampler->GetAt(StartIndex, &StartItem);
01833     double StartNewValue = (double)StartItem.m_Pressure; 
01834 
01835     // same for the end 
01836     CSampleItem EndItem; 
01837     if (ok) ok = pSampler->GetAt(EndIndex, &EndItem);
01838     double EndNewValue   = (double)EndItem.m_Pressure;
01839     
01840     // now we have our start and end values, we also need to know how many items to make
01841     // Given that we sample at the rate of MIN_BRUSH_SPACING this is fairly straightforward
01842     UINT32 NumObjects = NewPathLength / MIN_BRUSH_SPACING;
01843 
01844     // find out by how much we must increase/decrease by each time
01845     double Incr = (EndNewValue - StartNewValue)/NumObjects;
01846 
01847     // lets make our new sampler here
01848     CDistanceSampler* pNewSampler = new CDistanceSampler;
01849     if (pNewSampler == NULL)
01850         return NULL;
01851 
01852     if (!pNewSampler->InitialiseData(NumObjects))
01853     {
01854         delete pNewSampler;
01855         return NULL;
01856     }
01857 
01858     // now just loop through, adding items to the sampler
01859     CSampleItem NewItem;
01860     NewItem.m_Pressure = (UINT32)StartNewValue;
01861     ok = pNewSampler->SetAt(0, NewItem);
01862     while (NumObjects > 0 && ok)
01863     {
01864         NewItem.m_Pressure += (UINT32)Incr;
01865         ok = pNewSampler->SetNext(NewItem);
01866         NumObjects--;
01867     }
01868     return pNewSampler;
01869 }
01870 
01871 /********************************************************************************************
01872 
01873 >   BOOL OpDrawBrush::Declare()
01874 
01875     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01876     Created:    6/10/99
01877     Returns:    TRUE if all went OK, False otherwise
01878     Purpose:    Adds the operation to the list of all known operations
01879 
01880 ********************************************************************************************/
01881 
01882 BOOL OpDrawBrush::Declare()
01883 {
01884     return (RegisterOpDescriptor(
01885                                 0, 
01886                                 _R(IDS_FREE_HAND_TOOL),
01887                                 CC_RUNTIME_CLASS(OpDrawBrush), 
01888                                 OPTOKEN_DRAWBRUSH,
01889                                 OpDrawBrush::GetState,
01890                                 0,  /* help ID */
01891                                 _R(IDBBL_FREEHANDTOOLOP),
01892                                 0   /* bitmap ID */));
01893 }
01894 
01895 
01896 /********************************************************************************************
01897 
01898 >   OpState OpDrawBrush::GetState(String_256* Description, OpDescriptor*)
01899 
01900     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01901     Created:    6/10/99
01902     Outputs:    Description - GetState fills this string with an approriate description
01903                 of the current state of the push tool
01904     Returns:    The state of the operation, so that menu items (ticks and greying can be
01905                 done properly
01906     Purpose:    Find out the state of the operation at the specific time
01907 
01908 ********************************************************************************************/
01909 
01910 OpState OpDrawBrush::GetState(String_256* Description, OpDescriptor*)
01911 {
01912     OpState Blobby;
01913     
01914     return Blobby;
01915 }
01916 
01917 
01918 
01919 /********************************************************************************************
01920 
01921 >   void OpDrawBrush::AddPointsToPath(DocCoord Pos, Spread* pSpread)
01922 
01923     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01924     Created:    7/10/99
01925     Inputs:     Pos - The position of the mouse
01926                 pSpread - Pointer to the spread that we are drawing on
01927     Purpose:    Adds a new point to the path of mouse moves. When the drag
01928                 finishes the mouse moves will be smoothed
01929 
01930 ********************************************************************************************/
01931 
01932 void OpDrawBrush::AddPointsToPath(DocCoord PointerPos, Spread* pSpread)
01933 {
01934     // If this coord is the same as the last one, then do not bother adding to the track data
01935     if (PreviousPoint == PointerPos)
01936         return;
01937  
01938     // Insert the move
01939     if (TrackData->InsertLineTo(PointerPos))
01940     {
01941         // and add pressure info if needed
01942         if (AddPressureToPath)
01943         {
01944             TrackData->AddExtraInfo(CI_PRESSURE, FreeHandPressure);
01945         }
01946     }
01947     else
01948     {
01949         // Oh no, we ran out of mem in the middle of making a new path
01950         // Tidy up and report back to HQ
01951         EndDrag();
01952 
01953         // Tell the World that it all went horribly wrong
01954         InformError();
01955 
01956         // Remove it from the tree and delete it
01957         TrackData->ClearPath();
01958         
01959         // End this operation and return
01960         FailAndExecute();
01961         End();
01962         return;
01963     }
01964     
01965 //  RenderLine(m_pGRenderBrush, TrackData, TrackData->GetNumCoords()-1);
01966 
01967     // Make a note of the coord, inc the line count and mark joining to the start as active.
01968     PreviousPoint = PointerPos;
01969     LineSegmentCount++;
01970     CanLineJoin = TRUE;
01971 }
01972 
01973 
01974 
01975 /********************************************************************************************
01976 
01977 >   void OpDrawBrush::SetCursorAndStatus(CursorType CurType)
01978 
01979     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01980     Created:    4/7/2000
01981     Inputs:     CurType - The type of cursor to change to
01982     Purpose:    Overridden version for the brush, basically we do not offer any of the keyboard
01983                 options so we wish to keep the status line blank during brush operations
01984 ********************************************************************************************/
01985 
01986 void OpDrawBrush::SetCursorAndStatus(CursorType CurType)
01987 {
01988 // Now, if FlipCursor = TRUE, we flip it!
01989     static Cursor* WhichCursor;
01990     WhichCursor = NULL;
01991 
01992     switch (CurType)
01993     {
01994         case NORMAL_CURSOR:
01995             WhichCursor = pFreeHandCursor;
01996         break;
01997 
01998         case JOIN_CURSOR:
01999             WhichCursor = pJoinCursor;
02000         break;
02001 
02002         case MODIFY_CURSOR:
02003             WhichCursor = pModifyCursor;
02004         break;
02005 
02006         default:
02007             break;
02008     }
02009 
02010     if (mustClearStatusBar) // got to execute the following at least once so that we clear the status bar ....
02011     {
02012         String_256 StatusMsg("");
02013         // Change Status bar message and the cursor
02014         pApp->UpdateStatusBarText(&StatusMsg);
02015         mustClearStatusBar = FALSE;
02016     }
02017 
02018     if (WhichCursor != MyCurrentCursor)
02019     {
02020         String_256 StatusMsg(_T(""));
02021 
02022         switch (CurType)
02023         {
02024             case NORMAL_CURSOR:
02025             break;
02026 
02027             case JOIN_CURSOR:
02028                 StatusMsg.Load(_R(IDS_FREEHANDDRAGJOIN));
02029             break;
02030 
02031             case MODIFY_CURSOR:
02032                 StatusMsg.Load(_R(IDS_FREEHANDMODIFY));
02033             break;
02034 
02035             default:
02036                 break;
02037 
02038         }
02039         
02040         // Change Status bar message and the cursor
02041         pApp->UpdateStatusBarText(&StatusMsg);
02042         
02043         // set this cursor as the current cursor and immediately display it
02044         CursorStack::GSetTop(WhichCursor, CurrentCursorID);
02045 
02046         // remember this is our current cursor
02047         MyCurrentCursor = WhichCursor;
02048     }
02049 }
02050 
02051 /********************************************************************************************
02052 
02053 >   BOOL OpDrawBrush::InitialiseProcessPathDistance()
02054 
02055     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02056     Created:    28/11/99
02057     Inputs:     -
02058     Purpose:    To create a new path processor object
02059     SeeAlso:    -
02060 
02061 ********************************************************************************************/
02062 
02063 BOOL OpDrawBrush::InitialiseProcessPathDistance()
02064 {
02065     if (m_pProcPathDistance != NULL)
02066     {
02067         delete m_pProcPathDistance;
02068         m_pProcPathDistance = NULL;
02069     }
02070 
02071     m_pProcPathDistance = new ProcessPathDistance(750/2);
02072     if (m_pProcPathDistance == NULL)
02073     {
02074         InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
02075         return FALSE;
02076     }
02077     return TRUE;
02078 }
02079 
02080 /********************************************************************************************
02081 
02082 >   BOOL OpDrawBrush::InitialisePathProcessorBrush(BrushHandle Index, MILLIPOINT Distance = 0)
02083 
02084     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02085     Created:    28/11/99
02086     Inputs:     BrushIndex - index into the array of brush definitions stored in the brush component
02087                 Distance - the distance along the path that we are starting at
02088     Retruns:    TRUE if successful, FALSE otherwise
02089     Purpose:    To create a new pathprocessorbrush and copy all the data from the brush definitino
02090                 found using BrushIndex
02091     SeeAlso:    -
02092 
02093 ********************************************************************************************/
02094 
02095 BOOL OpDrawBrush::InitialisePathProcessorBrush(BrushHandle Handle, MILLIPOINT Distance)
02096 {
02097     // find the brush definition corresponding to the Handle
02098     Document* pDoc = Document::GetCurrent();
02099     ERROR2IF(pDoc == NULL, FALSE, "er, wheres the document gone");
02100     BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent((CC_RUNTIME_CLASS(BrushComponent)));
02101     ERROR2IF(pBrushComp == NULL, FALSE, "No brush component");
02102     BrushDefinition* pBrushDef = pBrushComp->FindBrushDefinition(Handle);
02103     ERROR2IF(pBrushDef == NULL, FALSE, "Couldn't find brush definition");
02104 
02105     // ask the definition to prepare for rendering
02106     if (!pBrushDef->StartRender())
02107         return FALSE;
02108     
02109     // check we haven't already allocated this member
02110     if (m_pPathProcBrush != NULL)
02111     {
02112         delete m_pPathProcBrush;
02113         m_pPathProcBrush = NULL;
02114     }
02115     // allocate the new path processor
02116     m_pPathProcBrush = new PathProcessorBrush;
02117     if (m_pPathProcBrush == NULL)
02118     {
02119         InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
02120         return FALSE;
02121     }
02122 
02123     // everything is ok so far, so transfer the data
02124     m_pPathProcBrush->SetBrushDefinition(Handle);
02125     pBrushDef->CopyDataToProcessor(m_pPathProcBrush);
02126     
02127 PORTNOTE("other", "Removed m_pGRenderBrush support")
02128 #ifndef EXCLUDE_FROM_XARALX
02129     // if our screen depth is < 24 BPP then we need to ensure that the scaling and offset
02130     // variations are turned off.
02131     if (m_pGRenderBrush->GetScreenDepth() < 24)
02132     {
02133         m_pPathProcBrush->SetBrushScalingIncr(1);
02134         m_pPathProcBrush->SetBrushScalingIncrConst(0);
02135     //  m_pPathProcBrush->SetScalingMaxPressure(0);
02136         m_pPathProcBrush->SetPathOffsetIncrConst(0);
02137         m_pPathProcBrush->SetPathOffsetIncrProp(1);
02138     //  m_pPathProcBrush->SetScalingMaxRand(0);
02139     }
02140 #endif
02141 
02142   // if we're not using pressure then turn it off
02143     if (!AddPressureToPath)
02144     {
02145         m_pPathProcBrush->SetScalingMaxPressure(0);
02146         m_pPathProcBrush->SetTransparencyPressure(0);
02147     }
02148 
02149     // do we need to scale to line width
02150     MILLIPOINT LineWidth = GetCurrentLineWidthIfNotDefault();
02151     if (LineWidth != -1)
02152     {
02153         if (LineWidth < 501)  // make sure we don't go too small
02154             LineWidth = 501;
02155         m_pPathProcBrush->ScaleToValue(LineWidth, !AddPressureToPath);
02156     }
02157     
02158     m_BrushScaling = m_pPathProcBrush->GetBrushScaling();
02159     
02160     m_pPathProcBrush->Reset();
02161     m_pPathProcBrush->SetCalculateBoundingBox(TRUE); // we want the bounding box
02162 
02163     // set up the arrays to hold cached transformation data
02164     if (!m_pPathProcBrush->PrepareForRenderingLoop(m_pPathProcBrush->GetNumBrushObjects()))
02165     {
02166         delete m_pPathProcBrush;
02167         return FALSE;
02168     }
02169 
02170 
02171     // if we are starting at some point along the path then advance our data to what it should be
02172     if (Distance)
02173         m_pPathProcBrush->AdvanceBrushToDistance(Distance);
02174 
02175     m_LastInkObjectRendered = m_pPathProcBrush->GetLastObject();
02176 
02177     // finally if this brush does not require pressure then turn it off
02178     if (!pBrushDef->UsesPressure())
02179         AddPressureToPath = FALSE;
02180 
02181 //#ifdef NEWFASTBRUSHES 
02182     m_pBrushDefinition = m_pPathProcBrush->GetOurBrushDefinition ();    // store this off here
02183     // old RenderBrushAtPoint would grab this for each iteration!
02184 //#endif
02185 
02186     return TRUE;
02187 }
02188 
02189 
02190 /********************************************************************************************
02191 
02192 >   BOOL OpDrawBrush::InitialisePressureCache()
02193 
02194     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02195     Created:    28/11/99
02196     Inputs:     -
02197     Purpose:    To allocate the pressure array, if we need it
02198     SeeAlso:    -
02199 
02200 ********************************************************************************************/
02201 
02202 BOOL OpDrawBrush::InitialisePressureCache()
02203 {
02204     // do we actually need to do this?
02205     if (!AddPressureToPath)
02206         return TRUE; 
02207     /*
02208     m_pPressureVals = new PressureArray;
02209     if (m_pPressureVals == NULL)
02210         return FALSE;
02211 
02212     // make it pretty big so we don't have to keep reallocating
02213     m_pPressureVals->SetSize(200, 10);
02214     */
02215 
02216     m_pPressureList = new PressureList;
02217     if (m_pPressureList == NULL)
02218         return FALSE;
02219 
02220     return TRUE;
02221 }
02222 
02223 /********************************************************************************************
02224 
02225 >   BOOL OpDrawBrush::InitialiseTimeStampList()
02226 
02227     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02228     Created:    28/11/99
02229     Inputs:     -
02230     Purpose:    to create a new timestamp object list and assign it to our member
02231     SeeAlso:    -
02232 
02233 ********************************************************************************************/
02234 
02235 BOOL OpDrawBrush::InitialiseTimeStampList()
02236 {
02237     // if we've already got one then delete it
02238     if (m_pTimeStampList != NULL)
02239     {
02240         delete m_pTimeStampList;
02241         m_pTimeStampList = NULL;
02242     }
02243     m_pTimeStampList = new TimeStampList;
02244     if (m_pTimeStampList == NULL)
02245         return FALSE;
02246 
02247     return TRUE;
02248 }
02249 
02250 
02251 /********************************************************************************************
02252 
02253 >   BOOL OpDrawBrush::SetTimeStamp(INT32 TimeStamp)
02254 
02255     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02256     Created:    28/11/99
02257     Inputs:     Value of timestamp to use in ms.
02258     Returns:    TRUE unless Timestamp is outside the specified bounds
02259     Purpose:    to set the timestamp member
02260     SeeAlso:    -
02261 
02262 ********************************************************************************************/
02263 
02264 BOOL OpDrawBrush::SetTimeStamp(double TimeStamp)
02265 {
02266     if (TimeStamp < MIN_TIMESTAMP || TimeStamp > MAX_TIMESTAMP)
02267         return FALSE;
02268 
02269     m_TimeStamp = TimeStamp;
02270     return TRUE;
02271 }
02272 
02273 
02274 /********************************************************************************************
02275 
02276 >   BOOL OpDrawBrush::InitialisePressureSampler()
02277 
02278     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02279     Created:    28/11/99
02280     Inputs:     -
02281     Returns:    TRUE if successful, FALSE if our allocation failed.
02282     Purpose:    to create a new CSampleData object and assign it to our pointer for sampling pressure
02283     SeeAlso:    -
02284 
02285 ********************************************************************************************/
02286 
02287 BOOL OpDrawBrush::InitialisePressureSampler()
02288 {
02289     if (m_pPressureSampler != NULL)
02290     {
02291         delete m_pPressureSampler;
02292         m_pPressureSampler = NULL;
02293     }
02294     if (!AddPressureToPath)
02295         return TRUE;
02296 
02297     m_pPressureSampler = new CDistanceSampler;
02298 
02299     if (m_pPressureSampler == NULL)
02300         return FALSE;
02301     
02302     // set the max pressure value from our device
02303     CCPen *pPen = pApp->GetPressurePen();
02304     UINT32 MaxPressure = MAXPRESSURE;
02305     if (pPen != NULL)
02306         MaxPressure = pPen->GetPressureMax();
02307     
02308     m_pPressureSampler->SetMaxPressure(MaxPressure);
02309 
02310     return m_pPressureSampler->InitialiseData(5000);
02311 
02312 }
02313 
02314 /********************************************************************************************
02315 
02316 >   MILLIPOINT OpDrawBrush::GetCurrentLineWidthIfNotDefault()
02317 
02318     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02319     Created:    25/5/2000
02320     Inputs:     -
02321     Outputs:    -
02322     Returns:    The current line width, UNLESS the current line width is the Default attribute,
02323                 in which case it returns -1
02324     Purpose:    In order to determine whether we have to tell the brush to scale to a new line
02325                 width or not.
02326 
02327 ********************************************************************************************/
02328 
02329 MILLIPOINT OpDrawBrush::GetCurrentLineWidthIfNotDefault()
02330 {
02331     MILLIPOINT Retval = -1;
02332 
02333     Document* pDoc = Document::GetCurrent();
02334     if (pDoc == NULL)
02335     {
02336         ERROR3("No document");
02337         return Retval;
02338     }
02339 
02340     AttributeManager* pAttrMgr = &(pDoc->GetAttributeMgr());
02341     if (pAttrMgr == NULL)
02342     {
02343         ERROR3("No attribute manager");
02344         return Retval;
02345     }
02346 
02347     AttrLineWidth* pAttr = (AttrLineWidth*)(pAttrMgr->GetCurrentAttribute(CC_RUNTIME_CLASS(NodeRenderableInk), CC_RUNTIME_CLASS(AttrLineWidth)));
02348 
02349     if (pAttr != NULL)
02350     {
02351         AttrLineWidth* pDefault = (AttrLineWidth*)(AttributeManager::GetDefaultAttribute(ATTR_LINEWIDTH));
02352         if (pDefault == NULL)
02353         {
02354             ERROR3("Unable to get default line width, theres no way this can happen Jim!");
02355             return Retval;
02356         }
02357         MILLIPOINT CurrentLineWidth = pAttr->Value.LineWidth;
02358         MILLIPOINT DefaultLineWidth = pDefault->Value.LineWidth;
02359 
02360         if (CurrentLineWidth != DefaultLineWidth -1) // for some reason the default is 501
02361             Retval = CurrentLineWidth;
02362         
02363         // it turns out that GetDefault returns a copy of the default, so we must delete it here
02364         delete pDefault;
02365     }
02366     return Retval;
02367 }
02368 
02369 
02370 
02372 //  OpChangeBrush  - to change the features of the brush
02374 
02375 
02376 /********************************************************************************************
02377 
02378 >   OpChangeBrush::OpChangeBrush()
02379 
02380     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02381     Created:    18/11/99
02382     Returns:    -
02383     Purpose:    Constructor
02384 
02385 ********************************************************************************************/
02386 
02387 OpChangeBrush::OpChangeBrush()
02388 {
02389      ChangeType = CHANGEBRUSH_NONE; 
02390 }
02391 
02392 
02393 
02394 /********************************************************************************************
02395 
02396 >   BOOL OpChangeBrush::Declare()
02397 
02398     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02399     Created:    18/11/99
02400     Returns:    TRUE if all went OK, FALSE otherwise
02401     Purpose:    Adds the operation to the list of all known operations
02402 
02403 ********************************************************************************************/
02404 
02405 BOOL OpChangeBrush::Declare()
02406 {
02407     return (RegisterOpDescriptor(
02408                                 0, 
02409                                 0,
02410                                 CC_RUNTIME_CLASS(OpChangeBrush), 
02411                                 OPTOKEN_CHANGEBRUSH,
02412                                 OpChangeBrush::GetState,
02413                                 0,  /* help ID */
02414                                 0,  /* bubble ID */
02415                                 0   /* bitmap ID */
02416                                 ));
02417 }
02418 
02419 
02420 
02421 /********************************************************************************************
02422 
02423 >   static OpState OpChangeBrush::GetState(String_256* Description, OpDescriptor*)
02424 
02425     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02426     Created:    18/11/99
02427     Outputs:    Description - GetState fills this string with an approriate description
02428                 of the current state of the operation 
02429     Returns:    The state of the operation, so that menu items (ticks and greying) can be
02430                 done properly
02431     Purpose:    Find out the state of the operation at the specific time
02432 
02433 ********************************************************************************************/
02434 
02435 OpState OpChangeBrush::GetState(String_256* Description, OpDescriptor*)
02436 {
02437     OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default
02438     
02439     /*
02440     List NodeList;
02441     BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeBrush));
02442 
02443     if (!NodeList.IsEmpty())
02444     {
02445         State.Greyed = FALSE;
02446     }
02447 
02448     NodeList.DeleteAll();   
02449     */
02450     // find out if there are any brushed nodes in the selection
02451     SelRange *pSel = GetApplication ()->FindSelection();
02452     if (pSel != NULL)
02453     {
02454         Node *pNode = pSel->FindFirst();
02455         while (pNode != NULL)
02456         {
02457             if (pNode->IsBrushed())
02458                 State.Greyed = FALSE;
02459             pNode = pSel->FindNext(pNode);
02460         }
02461     }
02462     return State;
02463 
02464 }
02465 
02466 /********************************************************************************************
02467 
02468 >   virtual void OpChangeBrush::GetOpName(String_256* OpName) 
02469 
02470     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02471     Created:    18/11/99
02472     Inputs:     -
02473     Outputs:    The undo string for the operation
02474     Returns:    
02475     Purpose:    The GetOpName fn is overridden so that we return back a description 
02476                 appropriate to the type of attribute that the operation applies. 
02477     Errors:     -
02478     SeeAlso:    -
02479 
02480 ********************************************************************************************/
02481 
02482 void OpChangeBrush::GetOpName(String_256* OpName) 
02483 { 
02484     UINT32 IDS = _R(IDS_MARKN_EMPTY);
02485 
02486     switch (ChangeType)
02487     {
02488         case CHANGEBRUSH_NONE:              break;
02489         case CHANGEBRUSH_SPACING:           IDS = _R(IDS_BRUSHSPACING_UNDO);    break;
02490         case CHANGEBRUSH_SPACING_INCRPROP:  IDS = _R(IDS_BRUSHSPACING_INCR);    break;
02491         case CHANGEBRUSH_SPACING_INCRCONST: IDS = _R(IDS_BRUSHSPACING_INCR);    break;
02492         case CHANGEBRUSH_SPACING_MAXRAND:   IDS = _R(IDS_BRUSHSPACING_MAXRAND); break;
02493         case CHANGEBRUSH_SPACING_RANDSEED:  IDS = _R(IDS_BRUSHSPACING_RANDSEED); break;
02494         case CHANGEBRUSH_SCALING:           IDS = _R(IDS_BRUSHSCALING_UNDO);    break;
02495         case CHANGEBRUSH_SCALING_INCR:      IDS = _R(IDS_BRUSHSCALING_INCR);    break;
02496         case CHANGEBRUSH_SCALING_INCRCONST: IDS = _R(IDS_BRUSHSCALING_INCR);    break;
02497         case CHANGEBRUSH_SCALING_MAXRAND:   IDS = _R(IDS_BRUSHSCALING_MAXRAND); break;
02498         case CHANGEBRUSH_SCALING_RANDSEED:  IDS = _R(IDS_BRUSHSCALING_RANDSEED); break;
02499         case CHANGEBRUSH_SCALING_PRESSURE:  IDS = _R(IDS_BRUSHSCALING_PRESSURE); break;
02500         case CHANGEBRUSH_OFFSET_TYPE:       IDS = _R(IDS_BRUSHOFFSET_TYPE_UNDO);break;
02501         case CHANGEBRUSH_OFFSET_TYPE_SEED:  IDS = _R(IDS_OFFSETTYPE_RANDSEED);  break;
02502         case CHANGEBRUSH_OFFSET_VAL:        IDS = _R(IDS_BRUSHOFFSET_VAL_UNDO); break;
02503         case CHANGEBRUSH_OFFSET_VALSEED:    IDS = _R(IDS_OFFSETVAL_RANDSEED);   break;
02504         case CHANGEBRUSH_OFFSET_SEEDS:      IDS = _R(IDS_OFFSETVAL_RANDSEED);   break;
02505         case CHANGEBRUSH_OFFSET_INCRPROP:   IDS = _R(IDS_BRUSHOFFSET_INCR);     break;
02506         case CHANGEBRUSH_OFFSET_INCRCONST:  IDS = _R(IDS_BRUSHOFFSET_INCR);     break;
02507         case CHANGEBRUSH_OFFSET_MAXRAND:    IDS = _R(IDS_OFFSETVAL_MAXRAND);    break;
02508         case CHANGEBRUSH_TILED:             IDS = _R(IDS_BRUSHTILE_UNDO);       break;
02509         case CHANGEBRUSH_TANGENTIAL:        IDS = _R(IDS_BRUSHROTATE_UNDO);     break;
02510         case CHANGEBRUSH_ROTATE_ANGLE:      IDS = _R(IDS_BRUSHROTATE_ANGLE_UNDO); break;
02511         case CHANGEBRUSH_ROTATE_INCRPROP:   IDS = _R(IDS_BRUSHROTATE_ANGLE_UNDO); break;
02512         case CHANGEBRUSH_ROTATE_INCRCONST:  IDS = _R(IDS_BRUSHROTATE_INCR);      break;
02513         case CHANGEBRUSH_ROTATE_PRESSURE:   IDS = _R(IDS_BRUSHROTATE_PRESSURE);  break;
02514         case CHANGEBRUSH_NAME:              IDS = _R(IDS_BRUSHNAME_UNDO);       break;
02515         case CHANGEBRUSH_SEQUENCE:          IDS = _R(IDS_BRUSHNAME_UNDO);       break;
02516         case CHANGEBRUSH_SEQUENCE_RANDSEED: IDS = _R(IDS_SEQUENCE_RANDSEED);    break;
02517         case CHANGEBRUSH_USELOCALFILLCOL:   IDS = _R(IDS_BRUSH_USELOCAL_FILLCOL);   break;
02518         case CHANGEBRUSH_USELOCALTRANSP:    IDS = _R(IDS_BRUSH_USELOCAL_TRANSP);    break;
02519         case CHANGEBRUSH_USENAMEDCOL:       IDS = _R(IDS_BRUSH_USELOCAL_FILLCOL);   break;
02520         case CHANGEBRUSH_ALL:               IDS = _R(IDS_BRUSH_CHANGEALL);      break;
02521         case CHANGEBRUSH_ROTATE_MAXRAND:    IDS = _R(IDS_ROTATE_MAXRAND);       break;
02522         case CHANGEBRUSH_ROTATE_RANDSEED:   IDS = _R(IDS_ROTATE_RANDSEED);      break;
02523         case CHANGEBRUSH_HUE_INCR:          IDS = _R(IDS_ROTATE_RANDSEED);      break;
02524         case CHANGEBRUSH_HUE_MAXRAND:       IDS = _R(IDS_BRUSH_HUE_RANDOM);     break;
02525         case CHANGEBRUSH_FILL_SEEDS:        IDS = _R(IDS_BRUSH_HUE_RANDSEED);   break;
02526         case CHANGEBRUSH_SAT_MAXRAND:       IDS = _R(IDS_BRUSH_SAT_RANDOM);     break;
02527         case CHANGEBRUSH_SAT_RANDSEED:      IDS = _R(IDS_BRUSH_SAT_RANDSEED);   break;
02528         case CHANGEBRUSH_TRANSP:            IDS = _R(IDS_BRUSHTRANSP);          break;
02529         case CHANGEBRUSH_TRANSP_PRESSURE:   IDS = _R(IDS_BRUSHTRANSP_PRESSURE); break;
02530         case CHANGEBRUSH_REGEN:             break;
02531         
02532         default: ERROR3_PF(("Unknown flag type (%d)",ChangeType));  break;
02533     }
02534 
02535     *OpName = String_256(IDS);
02536 }  
02537 
02538 
02539 /********************************************************************************************
02540 
02541 >   void OpChangeBrush::DoWithParam(OpDescriptor*,OpParam* pOpParam)
02542 
02543     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02544     Created:    18/11/99
02545     Returns:    -
02546     Purpose:    This changes the flag specified in FlagType (given in pOpParam->Param1) in all the 
02547                 selected brush objects to have the same as state of pOpParam->Param2.
02548 
02549 ********************************************************************************************/
02550 
02551 void OpChangeBrush::DoWithParam(OpDescriptor*,OpParam* pOpParam)
02552 {
02553     ERROR3IF(pOpParam == NULL,"NULL OpParam ptr");
02554     if (pOpParam == NULL) return;
02555 
02556     ChangeBrushOpParam* pChangeParam = (ChangeBrushOpParam*)pOpParam;
02557 
02558     // find all the brushes in the current selection
02559     List NodeList;
02560     BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeRenderableInk));
02561 
02562     BOOL ok = !NodeList.IsEmpty();
02563     if (ok) ok = DoStartSelOp(FALSE,FALSE);
02564 
02565     NodeListItem * pItem = NULL;
02566     
02567     Spread* pSpread = Document::GetSelectedSpread();
02568     if (pSpread == NULL)
02569     {
02570         ERROR3("Wheres the spread!?");
02571         return;
02572     }
02573     
02574     if (ok)
02575     {
02576         
02577         pItem = (NodeListItem *)NodeList.GetHead();
02578 
02579         Node* pSelNode = NULL;
02580 
02581         if (pItem)
02582         {
02583             pSelNode = pItem->pNode;
02584         }
02585         
02586         while (pSelNode != NULL && ok)
02587         {
02588             Node* pNode = pSelNode;
02589 
02590             pItem = (NodeListItem *)NodeList.GetNext(pItem);
02591 
02592             if (pItem)
02593             {
02594                 pSelNode = pItem->pNode;
02595             }
02596             else
02597             {
02598                 pSelNode = NULL;
02599             }
02600             
02601             AttrBrushType* pAttrBrush = ((NodeRenderableInk*)pNode)->GetAppliedBrushAttribute();
02602             if (pAttrBrush != NULL && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush)
02603             {
02604                 // We now have a selected node with a brush attribute so:
02605                 //  Invalidate the node's region
02606                 //  Store the current state of brush flag in an undo actiom
02607                 //  Change the flag to the setting in Param2
02608 
02609                 ChangeBrushAction* pAction;
02610     
02611                 
02612                 // Ask the node if it's ok to do the op
02613                 ObjChangeFlags cFlags;
02614                 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
02615                 ok = pNode->AllowOp(&ObjChange, TRUE);
02616             //  TRACEUSER( "Diccon", _T("CHANGE BRUSH ACTION\n"));
02617                 DocRect PreActRect =((NodeRenderableBounded*)pNode)->GetBoundingRect();
02618                 // invalidate the brush's region
02619                 if (ok) ok = DoInvalidateNodeRegion((NodeRenderableBounded*)pNode,TRUE,FALSE);
02620             //  if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,(NodeRenderableBounded*)pNode,TRUE) != AC_FAIL);
02621 
02622                 // invalidate it before
02623                 if (ok) ok = DoInvalidateRegion(pSpread, PreActRect);
02624                 
02625                 INT32 OldSize = pAttrBrush->GetDefaultLineWidth();
02626 
02627                 // change the brush in an undoable way
02628                 if (ok) ok = ChangeBrushAction::Init(this,&UndoActions,(NodeRenderableInk*)pNode,
02629                                                     pChangeParam,&pAction) != AC_FAIL;
02630                 
02631                 // have we changed the size of the brush? Depends on what our param says
02632                 INT32 NewSize = pAttrBrush->GetDefaultLineWidth();
02633                 
02634                 if (pChangeParam->ChangeLineWidth())
02635                 {
02636                     double SizeChange = (double)NewSize / (double)OldSize;
02637                     ok = ChangeLineWidth(SizeChange, (NodeRenderableInk*)pNode);
02638                 }
02639                 
02640                 DocRect PostActRect = ((NodeRenderableBounded*)pNode)->GetBoundingRect();
02641             
02642                 if (ok) ok = DoInvalidateNodeRegion((NodeRenderableBounded*)pNode,TRUE,FALSE);
02643             
02644                 // invalidate it after
02645                 if (ok) ok = DoInvalidateRegion(pSpread, PostActRect);
02646                 
02647             }
02648             
02649         }
02650     }
02651     NodeList.DeleteAll();
02652     
02653 
02654     if (ok) 
02655     {
02656         // Inform the effected parents of the change
02657         ObjChangeFlags cFlags;
02658         ObjChangeParam ObjChange(OBJCHANGE_FINISHED,cFlags,NULL,this);
02659         UpdateChangedNodes(&ObjChange);
02660 
02661         // Note the way the selected brush were changed
02662         ChangeType = pChangeParam->ChangeType;
02663     }
02664     else
02665         FailAndExecute();
02666 
02667     End();
02668 }
02669 
02670 
02671 
02672 /********************************************************************************************
02673 
02674 >   BOOL OpChangeBrush::ChangeLineWidth(const double &PropChange, NodeRenderableInk* pInk)
02675 
02676     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02677     Created:    18/11/99
02678     Inputs:     PropChange - the proportion to change the line width by (must be > 0)
02679                 pInk - the node whose line width we want to change
02680     Returns:    -
02681     Purpose:    To change the linewidth applied to pInk by the specified proportion
02682 
02683     Notes:      What we must do here is get in a situation where we have a line width attribut
02684                 that applies only to this ink node,as we don't want to be changing other peoples
02685                 line widths.  Therefore if pInk doesn't have a line width child we will make one for it
02686 
02687 ********************************************************************************************/
02688 
02689 BOOL OpChangeBrush::ChangeLineWidth(const double &PropChange, NodeRenderableInk* pInk)
02690 {
02691     ERROR2IF(PropChange <= 0, FALSE, "Negative value passed to OpChangeBrush::ChangeLineWidth");
02692     ERROR2IF(pInk == NULL, FALSE, "Null input pointer to OpChangeBrush::ChangeLineWidth");
02693 
02694     // first get our current line width
02695     AttrLineWidth* pLineWidth = NULL;
02696     
02697     // search for it underneath us, if we can't find it we'll make a new one
02698     Node* pNode = pInk->FindFirstChild();
02699     while (pNode != NULL)
02700     {
02701         if (pNode->IsAnAttribute() && ((NodeAttribute*)pNode)->IsALineWidthAttr())
02702         {
02703             pLineWidth = (AttrLineWidth*)pNode;
02704             break;
02705         }
02706         pNode = pNode->FindNext();
02707     }
02708     if (pLineWidth != NULL)
02709     {
02710         // Try to hide the Node    
02711         NodeHidden* Hidden; 
02712         ALLOC_WITH_FAIL(Hidden,(new NodeHidden(pLineWidth)),this);
02713         if (Hidden == NULL)
02714         {          
02715             return (FALSE); 
02716         }
02717 
02718         // Try to create a ShowNodeAction which will show the node that we have just hidden. 
02719         
02720         ShowNodeAction* UndoShowNodeAction; 
02721 
02722         if (ShowNodeAction::Init(this,  
02723                                  &UndoActions, 
02724                                  Hidden, 
02725                                  TRUE, 
02726                                  (Action**)(&UndoShowNodeAction),
02727                                  TRUE) == AC_FAIL)
02728         {   
02729             // We must unhide the NodeToHide manually, cos no action will do it for us 
02730             Hidden->ShowNode(); // Hidden is deleted don't worry 
02731             return FALSE; 
02732         }
02733     }
02734     else
02735     {
02736         // there isn't a line width child, so we must be in a compound node or something.
02737         pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrLineWidth), (NodeAttribute**)&pLineWidth);
02738 
02739         if (pInk == NULL)
02740         {
02741             ERROR3("Unable to find line width node");
02742             return FALSE;
02743         }
02744     }
02745 
02746     // Make a new line width to insert
02747     AttrLineWidth* pNewLineWidth = new AttrLineWidth;
02748     if (pNewLineWidth == NULL)
02749     {
02750         ERROR1RAW(_R(IDE_NOMORE_MEMORY));
02751         return FALSE;
02752     }
02753 
02754     // insert the new attribute
02755     pNewLineWidth->AttachNode(pInk, FIRSTCHILD);
02756 
02757     // Create a hide node action to hide the node when we undo 
02758     HideNodeAction* UndoHideNodeAction;     
02759     if (HideNodeAction::Init(this, &UndoActions, pNewLineWidth,  TRUE,  ( Action**)(&UndoHideNodeAction))      
02760                               == AC_FAIL)
02761     {
02762         delete pNewLineWidth;
02763         return FALSE;
02764     }
02765 
02766     
02767 
02768     double OldWidth = (double)pLineWidth->Value.LineWidth;
02769     double NewWidth = OldWidth * PropChange;
02770     
02771     pNewLineWidth->Value.LineWidth = (MILLIPOINT)NewWidth;
02772 
02773     // change the control by abusing an op descriptor
02774     OpChangeLineWidthOpDesc* pDesc = (OpChangeLineWidthOpDesc*)OpDescriptor::FindOpDescriptor(OPTOKEN_CHANGELINEWIDTH);
02775     if (pDesc)
02776     {
02777         String_256 StrWidth = TEXT("");
02778         Convert::DoubleToString(NewWidth*0.001, &StrWidth, 2);
02779         StrWidth += TEXT("pt");
02780         pDesc->SetLineWidthGadgets(StrWidth);
02781     }
02782 
02783 
02784     return TRUE;
02785 
02786 }
02787 
02788 
02789 
02790 //------------------------------------------------------------------------------------------------
02791 //------------------------------------------------------------------------------------------------
02792 //------------------------------------------------------------------------------------------------
02793 // The ChangeBrushAction class
02794 
02795 /********************************************************************************************
02796 
02797 >   ChangeBrushAction::ChangeBrushAction()
02798 
02799     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02800     Created:    18/11/99
02801     Inputs:     -
02802     Outputs:    -
02803     Returns:    -
02804     Purpose:    Constructor for the action
02805     Errors:     -
02806     SeeAlso:    -
02807 
02808 ********************************************************************************************/
02809 
02810 ChangeBrushAction::ChangeBrushAction()
02811 {
02812     m_pBrushedNode  = NULL;
02813 }
02814 
02815 
02816 /********************************************************************************************
02817 
02818 >   ChangeBrushAction::~ChangeBrushAction()
02819 
02820     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02821     Created:    18/11/99
02822     Inputs:     -
02823     Outputs:    -
02824     Returns:    -
02825     Purpose:    destructor for the action
02826     Errors:     -
02827     SeeAlso:    -
02828 
02829 ********************************************************************************************/
02830 
02831 
02832 ChangeBrushAction::~ChangeBrushAction()
02833 {
02834 }
02835 
02836 /********************************************************************************************
02837 
02838 >   ActionCode ChangeBrushAction::Init(     Operation*      pOp,
02839                                             ActionList*     pActionList,
02840                                             NodeRenderableInk * pNodeBrush,
02841                                             ChangeBrushOpParam  *pChangeParam,
02842                                             ChangeBrushAction** ppNewAction);
02843 
02844     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02845     Created:    18/11/99
02846     Inputs:     pOp             = ptr to the operation to which this action belongs
02847                 pActionList     =  ptr to action list to which this action should be added
02848                 pBrushedNode    = ptr to node with brush attribute to change 
02849                 pChangeParam    = ptr to class that details how the blend should be changed.
02850     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
02851                                   a pointer to the created action
02852     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02853     Purpose:    This is the function which creates an instance of this action. If there is no room 
02854                 in the undo buffer (which is determined by the base class Init function called within)
02855                 the function will either return AC_NO_RECORD which means the operation can continue, 
02856                 but no undo information needs to be stored, or AC_OK which means the operation should
02857                 continue AND record undo information. If the function returns AC_FAIL, there was not 
02858                 enough memory to record the undo information, and the user has decided not to continue
02859                 with the operation.
02860 
02861                 This function actually changes the blend node in a way specified in pChangeParam
02862     Errors:     -
02863     SeeAlso:    Action::Init()
02864 
02865 ********************************************************************************************/
02866 
02867 
02868 
02869 ActionCode ChangeBrushAction::Init( Operation*          pOp,
02870                                     ActionList*         pActionList,
02871                                     NodeRenderableInk*  pBrushedNode,
02872                                     ChangeBrushOpParam* pChangeParam,
02873                                     ChangeBrushAction** ppNewAction)
02874 {
02875     ERROR2IF(pBrushedNode == NULL,AC_FAIL,"pNodeBrush is NULL");
02876     ERROR2IF(pChangeParam == NULL,AC_FAIL,"pChangeParam is NULL");
02877 
02878     // just check that we do actually have a brush attribute
02879     
02880 /*  NodeAttribute* pAttr = NULL;
02881     pBrushedNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr);
02882     ERROR2IF(pAttr == NULL, AC_FAIL, "No applied brush attribute");*/
02883 
02884     AttrBrushType* pAttrBrush = GetAttrBrush(pBrushedNode);
02885     if (pAttrBrush == NULL)
02886     {
02887         ERROR3("AttrBrushType is NULL in ChangeBrushAction::Init");
02888         return AC_FAIL;
02889     }
02890     if (pAttrBrush->GetBrushHandle() == BrushHandle_NoBrush)
02891     {
02892     //  ERROR3("Brush handle = BrushHandle_NoBrush in ChangeBrushAction::Init");
02893         return AC_OK;
02894     }
02895 
02896     // make the new action
02897     UINT32 ActSize = sizeof(ChangeBrushAction);
02898     ChangeBrushAction* pNewAction;
02899     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ChangeBrushAction),(Action**)&pNewAction);
02900     *ppNewAction = pNewAction;
02901 
02902     if (Ac != AC_FAIL && pNewAction != NULL)
02903     {
02904         ChangeBrushType ChangeType = pChangeParam->ChangeType;
02905 
02906         // set data in the new action
02907         pNewAction->m_pBrushedNode           = pBrushedNode;
02908         pNewAction->m_ChangeParam.ChangeType = ChangeType;
02909         pNewAction->m_ChangeParam.SetOldValues(pAttrBrush);
02910         
02911         if (!ChangeBrush(pChangeParam, pAttrBrush))
02912             Ac = AC_FAIL;
02913 
02914         pBrushedNode->InvalidateBoundingRect();
02915         pNewAction->m_ChangeParam.SetNewValues(pAttrBrush);
02916     } // end if (AC != ..
02917 
02918     return Ac;
02919 }
02920 
02921 
02922 
02923 /********************************************************************************************
02924 
02925 >   ActionCode ChangeBrushAction::Execute();
02926 
02927     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02928     Created:    18/11/99
02929     Inputs:     -
02930     Outputs:    -
02931     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02932     Purpose:    Executes the action.  This will reset the brush variables to their old values
02933     Errors:     -
02934     SeeAlso:    Action::Init()
02935 
02936 ********************************************************************************************/
02937 
02938 ActionCode ChangeBrushAction::Execute()
02939 {
02940     m_ChangeParam.SwapOldAndNew();
02941 
02942     ActionCode Act;
02943     ChangeBrushAction* pAction;
02944     TRACEUSER( "Diccon", _T("Undoing Change Brush Action\n"));
02945     Act = ChangeBrushAction::Init(pOperation,pOppositeActLst,m_pBrushedNode,&m_ChangeParam,&pAction);
02946 
02947     return Act;
02948 }
02949 
02950 
02951 /********************************************************************************************
02952 
02953 >   ActionCode ChangeBrushAction::Execute();
02954 
02955     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02956     Created:    18/11/99
02957     Inputs:     pInk - the ink node that has the applied brush
02958     Outputs:    -
02959     Returns:    the applied brush attribute
02960     Purpose:    Returns the brush attribute that applies to this node.  However there is a little
02961                 trickery needed to cope with the likes of shadow nodes etc. as the brushed node
02962                 will be a sibling of that node.
02963 
02964     Errors:     -
02965     SeeAlso:    Action::Init()
02966 
02967 ********************************************************************************************/
02968 
02969 AttrBrushType* ChangeBrushAction::GetAttrBrush(NodeRenderableInk* pInk)
02970 {
02971     NodeAttribute* pAttr = NULL;
02972     
02973     if (pInk->IS_KIND_OF(NodeShadow) || pInk->IS_KIND_OF(NodeBevel) || pInk->IS_KIND_OF(NodeContour))
02974     {
02975         // cycle through the siblings and see if one has an AttrBrushType as a child
02976         BOOL Found = FALSE;
02977         Node* pSibling = pInk->FindNext();
02978         while (pSibling != NULL && Found == FALSE)
02979         {
02980             Node* pChild = pSibling->FindFirstChild();
02981             while (pChild != NULL && !Found)
02982             {
02983                 if (pChild->IS_KIND_OF(AttrBrushType))
02984                 {
02985                     pAttr = (NodeAttribute*)pChild;
02986                     Found = TRUE;
02987                     break;
02988                 }
02989                 pChild = pChild->FindNext();
02990             }
02991             pSibling = pSibling->FindNext();
02992         }
02993     }
02994     else
02995         pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr);
02996 
02997     return (AttrBrushType*)pAttr;
02998 }
02999 
03000 
03001 /********************************************************************************************
03002 
03003 >   BOOL ChangeBrushAction::ChangeBrush(ChangeBrushOpParam* pParam, AttrBrushType* pBrush)
03004 
03005     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03006     Created:    18/10/2000
03007     Inputs:     pParam - object containing the data about what to change
03008                 pBrush - the brush attribute to be changed
03009     Outputs:    -
03010     Returns:    TRUE if successful, ,FALSE otherwise
03011     Purpose:    Changes pBrush according to the data provided in pParam
03012 
03013     Errors:     -
03014     SeeAlso:    Action::Init()
03015 
03016 ********************************************************************************************/
03017 
03018 BOOL ChangeBrushAction::ChangeBrush(ChangeBrushOpParam* pChangeParam, AttrBrushType* pAttrBrush)
03019 {
03020     ERROR2IF(pChangeParam == NULL || pAttrBrush == NULL, FALSE, "Invalid inputs to ChangeBrushAction::ChangeBrush");
03021 
03022     ChangeBrushType ChangeType = pChangeParam->ChangeType;
03023     
03024     BOOL Retval = FALSE;
03025 
03026     switch (ChangeType)
03027     {
03028         case CHANGEBRUSH_SPACING:           
03029             Retval = ChangeBrushSpacing(pChangeParam->m_NewSpacing, 
03030                                     pChangeParam->m_pPressure,  pAttrBrush);
03031             
03032             break;
03033         case CHANGEBRUSH_SPACING_INCRPROP:
03034             Retval = ChangeSpacingIncrProp(pChangeParam->m_NewSpacingIncrProp, pChangeParam->m_pPressure, pAttrBrush);
03035             break;
03036         case CHANGEBRUSH_SPACING_INCRCONST:
03037             Retval = ChangeSpacingIncrConst(pChangeParam->m_NewSpacingIncrConst, pChangeParam->m_pPressure, pAttrBrush);
03038             break;
03039         case CHANGEBRUSH_SCALING_INCR:
03040             Retval = ChangeScalingIncr(pChangeParam->m_NewScalingIncr, pAttrBrush);
03041             break;
03042         case  CHANGEBRUSH_SCALING_INCRCONST:
03043             Retval = ChangeScalingIncrConst(pChangeParam->m_NewScalingIncrConst, pAttrBrush);
03044             break;
03045         case CHANGEBRUSH_SCALING:
03046             Retval = ChangeBrushScaling(pChangeParam->m_NewScaling, pAttrBrush);
03047             break;
03048         case CHANGEBRUSH_SCALING_MAXRAND:
03049             Retval = ChangeScalingMaxRand(pChangeParam->m_NewScalingMaxRand, pAttrBrush);
03050             break;
03051         case CHANGEBRUSH_SCALING_RANDSEED:
03052             Retval = ChangeScalingRandSeed(pChangeParam->m_NewScalingRandSeed, pAttrBrush);
03053             break;
03054         case CHANGEBRUSH_SCALING_PRESSURE:
03055             Retval = ChangeScalingPressure(pChangeParam->m_NewScalingMaxPressure, pAttrBrush);
03056             break;
03057         case CHANGEBRUSH_TILED:
03058             Retval = ChangeBrushTile(pChangeParam->m_bNewTiled, pAttrBrush);
03059             break;
03060         case CHANGEBRUSH_TANGENTIAL:
03061             Retval = ChangeTangential(pChangeParam->m_bNewRotated, pAttrBrush);
03062             break;
03063         case CHANGEBRUSH_OFFSET_TYPE:
03064             Retval = ChangeOffsetType(pChangeParam->m_NewPathOffsetType, pAttrBrush);
03065             break;
03066         case CHANGEBRUSH_OFFSET_TYPE_SEED:
03067             Retval = ChangeOffsetTypeSeed(pChangeParam->m_NewOffsetTypeRandSeed, pAttrBrush);
03068             break;
03069         case CHANGEBRUSH_OFFSET_SEEDS:
03070             Retval = ChangeOffsetSeeds(pChangeParam->m_NewOffsetTypeRandSeed, pChangeParam->m_NewOffsetValRandSeed,
03071                                     pAttrBrush);
03072             break;
03073         case CHANGEBRUSH_OFFSET_VAL:
03074             Retval = ChangeOffsetValue(pChangeParam->m_NewPathOffsetVal, pAttrBrush);
03075             break;
03076         case CHANGEBRUSH_OFFSET_INCRPROP:
03077             Retval = ChangeOffsetIncrProp(pChangeParam->m_NewOffsetIncrProp, pAttrBrush);
03078             break;
03079         case CHANGEBRUSH_OFFSET_INCRCONST:
03080             Retval = ChangeOffsetIncrConst(pChangeParam->m_NewOffsetIncrConst, pAttrBrush);
03081             break;
03082         case CHANGEBRUSH_OFFSET_MAXRAND:
03083             Retval = ChangeOffsetValMaxRand(pChangeParam->m_NewOffsetValMaxRand, pAttrBrush);
03084             break;
03085         case CHANGEBRUSH_OFFSET_VALSEED:
03086             Retval = ChangeOffsetValRandSeed(pChangeParam->m_NewOffsetValRandSeed, pAttrBrush);
03087             break;
03088         case CHANGEBRUSH_ROTATE_ANGLE:
03089             Retval = ChangeRotation(pChangeParam->m_NewRotateAngle, pAttrBrush);
03090             break;
03091         case CHANGEBRUSH_ROTATE_INCRPROP:
03092             Retval = ChangeRotationIncrProp(pChangeParam->m_NewRotationIncrProp, pAttrBrush);
03093             break;
03094         case CHANGEBRUSH_ROTATE_INCRCONST:
03095             Retval = ChangeRotationIncrConst(pChangeParam->m_NewRotationIncrConst, pAttrBrush);
03096             break;
03097         case CHANGEBRUSH_ROTATE_MAXRAND:
03098             Retval = ChangeRotationMaxRand(pChangeParam->m_NewRotateMaxRand, pAttrBrush);
03099             break;
03100         case CHANGEBRUSH_ROTATE_RANDSEED:
03101             Retval = ChangeRotationRandSeed(pChangeParam->m_NewRotateRandSeed, pAttrBrush);
03102             break;
03103         case CHANGEBRUSH_ROTATE_PRESSURE:
03104             Retval = ChangeRotationMaxPressure(pChangeParam->m_NewRotationMaxPressure, pAttrBrush);
03105             break;
03106         case CHANGEBRUSH_SPACING_MAXRAND:
03107             Retval = ChangeSpacingMaxRand(pChangeParam->m_NewSpacingMaxRand, pAttrBrush);
03108             break;
03109         case CHANGEBRUSH_SPACING_RANDSEED:
03110             Retval = ChangeSpacingRandSeed(pChangeParam->m_NewSpacingRandSeed, pAttrBrush);
03111             break;
03112         case CHANGEBRUSH_USELOCALFILLCOL:
03113             Retval = ChangeUseLocalFillColour(pChangeParam->m_bNewUseLocalFillColour, pAttrBrush);
03114             break;
03115         case CHANGEBRUSH_USELOCALTRANSP:
03116             Retval = ChangeUseLocalTransp(pChangeParam->m_bNewUseLocalTransp, pAttrBrush);
03117             break;
03118         case CHANGEBRUSH_USENAMEDCOL:
03119             Retval = ChangeUseNamedColour(pChangeParam->m_bNewUseNamed, pAttrBrush);
03120             break;
03121         case CHANGEBRUSH_SEQUENCE:
03122             Retval = ChangeSequenceType(pChangeParam->m_NewSequenceType, pAttrBrush);
03123             break;
03124         case CHANGEBRUSH_SEQUENCE_RANDSEED:
03125             Retval = ChangeSequenceSeed(pChangeParam->m_NewSequenceRandSeed, pAttrBrush);
03126             break;
03127         case CHANGEBRUSH_ALL:
03128             Retval = ChangeAll(pChangeParam, pAttrBrush);
03129             break;
03130         case CHANGEBRUSH_TIMESTAMP:
03131             break;
03132         case CHANGEBRUSH_HUE_INCR:
03133             Retval = ChangeHueIncrement(pChangeParam->m_NewHueIncrement, pAttrBrush);
03134             break;
03135         case CHANGEBRUSH_HUE_MAXRAND:
03136             Retval = ChangeHueMaxRand(pChangeParam->m_NewHueMaxRand, pAttrBrush);
03137             break;
03138         case CHANGEBRUSH_FILL_SEEDS:
03139             Retval = ChangeFillSeeds(pChangeParam->m_NewHueRandSeed, pChangeParam->m_NewSatRandSeed,
03140                                 pAttrBrush);
03141             break;
03142         case CHANGEBRUSH_SAT_MAXRAND:
03143             Retval = ChangeSatMaxRand(pChangeParam->m_NewSatMaxRand, pAttrBrush);
03144             break;
03145         case CHANGEBRUSH_SAT_RANDSEED:
03146             Retval = ChangeSatRandSeed(pChangeParam->m_NewSatRandSeed, pAttrBrush);
03147             break;
03148         case CHANGEBRUSH_TRANSP:
03149             Retval = ChangeTransparency(pChangeParam->m_NewTransp, pAttrBrush);
03150             break;
03151         case CHANGEBRUSH_TRANSP_PRESSURE:
03152             Retval = ChangeTranspPressure(pChangeParam->m_NewTranspPressure, pAttrBrush);
03153             break;
03154 
03155         default : ERROR2(FALSE,"Unknown change brush type"); break;
03156         
03157     } // end switch
03158     return Retval;
03159 }
03160 
03161 
03162 /********************************************************************************************
03163 
03164 >   BOOL ChangeBrushAction::ChangeSelectionNoUndo(ChangeBrushOpParam* pParam)
03165 
03166     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03167     Created:    18/10/2000
03168     Inputs:     pParam - object containing the data about what to change
03169     Outputs:    -
03170     Returns:    TRUE if successful, ,FALSE otherwise
03171     Purpose:    In order to avoid generating undo information for each single slider movement
03172                 in the brush edit dialog I am introducing this system where we only generate
03173                 an undoable action on a slider_pos_set message.  For slider moving messages we
03174                 call this method, which will any brushes in the selection but not generate any undo
03175                 information.
03176 
03177                 This is potentially a bit naughty as it means we bypass the AllowOp mechanism
03178                 but its been given to me as a showstopper...
03179 
03180     Errors:     -
03181     SeeAlso:    Action::ChangeBrush()
03182 
03183 ********************************************************************************************/
03184 
03185 BOOL ChangeBrushAction::ChangeSelectionNoUndo(ChangeBrushOpParam* pParam)
03186 {
03187     PORTNOTETRACE("other","ChangeBrushAction::ChangeSelectionNoUndo - do nothing");
03188 #ifndef EXCLUDE_FROM_XARALX
03189     ERROR2IF(pParam == NULL, FALSE, "Invalid inputs to ChangeBrushAction::ChangeSelectionNoUndo");
03190 
03191     // find all the brushes in the current selection
03192     List NodeList;
03193     BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeRenderableInk));
03194 
03195     BOOL ok = !NodeList.IsEmpty();
03196 
03197     NodeListItem * pItem = NULL;
03198     
03199     Spread* pSpread = Document::GetSelectedSpread();
03200     if (pSpread == NULL)
03201     {
03202         ERROR3("Wheres the spread!?");
03203         return FALSE;
03204     }
03205     DocView* pDocView = DocView::GetCurrent();
03206     if (pDocView == NULL)
03207     {
03208         ERROR3("No DocView!");
03209         return FALSE;
03210     }
03211     
03212     if (ok)
03213     {
03214         
03215         pItem = (NodeListItem *)NodeList.GetHead();
03216 
03217         Node* pSelNode = NULL;
03218 
03219         if (pItem)
03220         {
03221             pSelNode = pItem->pNode;
03222         }
03223         
03224         AttrBrushType* pAttrBrush = NULL;
03225         
03226         while (pSelNode != NULL && ok)
03227         {
03228             Node* pNode = pSelNode;
03229 
03230             pItem = (NodeListItem *)NodeList.GetNext(pItem);
03231 
03232             if (pItem)
03233             {
03234                 pSelNode = pItem->pNode;
03235             }
03236             else
03237             {
03238                 pSelNode = NULL;
03239             }
03240             
03241             pAttrBrush = GetAttrBrush((NodeRenderableInk*)pNode);
03242     
03243             if (pAttrBrush != NULL && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush)          
03244             {
03245                 // invalidate it before
03246                 DocRect PreActRect = ((NodeRenderableBounded*)pNode)->GetBoundingRect();
03247                 if (pNode->IsAnObject()) ((NodeRenderableInk*)pNode)->ReleaseCached();
03248                 if (ok) 
03249                     pDocView->ForceRedraw(pSpread, PreActRect);
03250 
03251                 // make sure we recalculate the rect
03252                 ((NodeRenderableBounded*)pNode)->InvalidateBoundingRect();
03253 
03254                     
03255                 INT32 OldSize = pAttrBrush->GetDefaultLineWidth();
03256 
03257                 // change the brush in an non-undoable way
03258                 if (ok) ok = ChangeBrush(pParam, pAttrBrush);
03259                 
03260 
03261                 // have we changed the size of the brush?  If so then we will have applied a new line width
03262                 // in the action, so factor out
03263                 INT32 NewSize = pAttrBrush->GetDefaultLineWidth();
03264                 
03265                 if (NewSize != OldSize && ok)
03266                 {
03267                     double SizeChange = (double)NewSize / (double)OldSize;
03268                     ok = ChangeLineWidthChildNoUndo(SizeChange, (NodeRenderableInk*)pNode);
03269                 }
03270                 
03271             
03272                 DocRect PostActRect = ((NodeRenderableBounded*)pNode)->GetBoundingRect();
03273             
03274                 if (pNode->IsAnObject()) ((NodeRenderableInk*)pNode)->ReleaseCached();
03275                 
03276                 // invalidate it after
03277                 if (ok)
03278                     pDocView->ForceRedraw(pSpread, PostActRect);
03279                 
03280             }
03281             
03282         }
03283     }
03284     NodeList.DeleteAll();
03285     
03286     return ok;
03287 #else
03288     return FALSE;
03289 #endif
03290 }
03291 
03292 
03293 /********************************************************************************************
03294 
03295 >   BOOL ChangeBrushAction::ChangeLineWidthNoUndo(double ChangeProp, NodeRenderableInk* pInk)
03296 
03297     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03298     Created:    18/11/99
03299     Inputs:     ChangeProp - the proportion to change the line width by
03300                 pInk - the ink node to search under
03301     Outputs:    -
03302     Returns:    TRUE if successful, FALSE otherwise
03303     Purpose:    To change the line width of the child attribute if this ink node.  Note that 
03304                 we only change child attributes because we don't want to mess up any other inknodes
03305     SeeAlso:    -
03306 
03307 ********************************************************************************************/
03308 
03309 BOOL ChangeBrushAction::ChangeLineWidthChildNoUndo(double ChangeProp, NodeRenderableInk* pInk)
03310 {
03311     PORTNOTETRACE("other","ChangeBrushAction::ChangeLineWidthChildNoUndo - do nothing");
03312 #ifndef EXCLUDE_FROM_XARALX
03313     ERROR2IF(ChangeProp <= 0.0, FALSE, "Invalid change proportion in ChangeBrushAction::ChangeLineWidthChildNoUndo");
03314     ERROR2IF(pInk == NULL, FALSE, "Ink node is NULL in ChangeBrushAction::ChangeLineWidthChildNoUndo");
03315 
03316     // search for the line width attribute
03317     Node* pNode = pInk->FindFirstChild();
03318     AttrLineWidth* pLineWidth = NULL;
03319     
03320     while (pNode != NULL)
03321     {
03322         if (pNode->IsAnAttribute() && ((NodeAttribute*)pNode)->IsALineWidthAttr())
03323         {
03324             pLineWidth = (AttrLineWidth*)pNode;
03325             break;
03326         }
03327         pNode = pNode->FindNext();
03328     }
03329 
03330     if (pLineWidth == NULL)
03331         return FALSE;
03332 
03333     // get the old value, multiply by our proportion
03334     double OldWidth = (double)pLineWidth->Value.LineWidth;
03335     double NewWidth = OldWidth * ChangeProp;
03336     
03337     pLineWidth->Value.LineWidth = (MILLIPOINT)NewWidth;
03338 
03339     // change the line width gadgets by abusing an op descriptor
03340     OpChangeLineWidthOpDesc* pDesc = (OpChangeLineWidthOpDesc*)OpDescriptor::FindOpDescriptor(OPTOKEN_CHANGELINEWIDTH);
03341     if (pDesc)
03342     {
03343         String_256 StrWidth = TEXT("");
03344         Convert::DoubleToString(NewWidth*0.001, &StrWidth, 2);
03345         StrWidth += TEXT("pt");
03346         pDesc->SetLineWidthGadgets(StrWidth);
03347     }
03348 
03349     return TRUE;
03350 #else
03351     return FALSE;
03352 #endif
03353 }
03354 
03355 
03356 /********************************************************************************************
03357 
03358 >   BOOL ChangeBrushAction::ChangeBrushSpacing(MILLIPOINT NewSpacing, AttrBrushType* pAttrBrush)
03359 
03360     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03361     Created:    18/11/99
03362     Inputs:     NewSpacing - the value to set       
03363     Outputs:    pAttrBrush - the brush attribute to change
03364     Returns:    TRUE if successful, FALSE otherwise
03365     Purpose:    To set the brush spacing of this attribute node
03366     SeeAlso:    -
03367 
03368 ********************************************************************************************/
03369 
03370 BOOL ChangeBrushAction::ChangeBrushSpacing(MILLIPOINT NewSpacing, PressureArray* pArray,
03371                                            AttrBrushType* pAttrBrush)
03372 {
03373     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03374 //  if (pArray != NULL)
03375 //      pAttrBrush->SetPressureCache(pArray);
03376     return pAttrBrush->SetSpacing(NewSpacing);
03377 }
03378 
03379 
03380 /********************************************************************************************
03381 
03382 >   BOOL ChangeBrushAction::ChangeSpacingIncrProp(double NewIncrProp, AttrBrushType* pAttrBrush)
03383 
03384     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03385     Created:    18/11/99
03386     Inputs:     NewSpacing - the value to set       
03387     Outputs:    pAttrBrush - the brush attribute to change
03388     Returns:    TRUE if successful, FALSE otherwise
03389     Purpose:    To set the brush spacing of this attribute node
03390     SeeAlso:    -
03391 
03392 ********************************************************************************************/
03393 
03394 BOOL ChangeBrushAction::ChangeSpacingIncrProp(double NewIncr, PressureArray* pArray, AttrBrushType* pAttrBrush)
03395 {
03396     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03397 //  if (pArray != NULL)
03398     //  pAttrBrush->SetPressureCache(pArray);
03399 
03400         // get the path processor
03401     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03402     if (pPPB == NULL)
03403         return FALSE;
03404 
03405     return pPPB->SetSpacingIncrProp(NewIncr);
03406 }
03407 
03408 
03409 /********************************************************************************************
03410 
03411 >   BOOL ChangeBrushAction::ChangeSpacingIncrConst(MILLIPOINT NewIncr, AttrBrushType* pAttrBrush)
03412 
03413     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03414     Created:    18/11/99
03415     Inputs:     NewSpacing - the value to set       
03416     Outputs:    pAttrBrush - the brush attribute to change
03417     Returns:    TRUE if successful, FALSE otherwise
03418     Purpose:    To set the brush spacing of this attribute node
03419     SeeAlso:    -
03420 
03421 ********************************************************************************************/
03422 
03423 BOOL ChangeBrushAction::ChangeSpacingIncrConst(MILLIPOINT NewIncr, PressureArray* pArray, AttrBrushType* pAttrBrush)
03424 {
03425     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03426     //if (pArray != NULL)
03427     //  pAttrBrush->SetPressureCache(pArray);
03428 
03429         // get the path processor
03430     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03431     if (pPPB == NULL)
03432         return FALSE;
03433 
03434     return pPPB->SetSpacingIncrConst(NewIncr);
03435 }
03436 
03437 
03438 /********************************************************************************************
03439 
03440 >   BOOL ChangeBrushAction::ChangeBrushScaling(double NewScaling, AttrBrushType* pAttrBrush)
03441 
03442     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03443     Created:    18/11/99
03444     Inputs:     NewScaling - the value to set       
03445     Outputs:    pAttrBrush - the brush attribute to change
03446     Returns:    TRUE if successful, FALSE otherwise
03447     Purpose:    To set the brush scaling of this attribute node
03448     SeeAlso:    -
03449 
03450 ********************************************************************************************/
03451 
03452 BOOL ChangeBrushAction::ChangeBrushScaling(double NewScaling, AttrBrushType* pAttrBrush)
03453 {
03454     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03455     
03456     // get the path processor
03457     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03458     if (pPPB == NULL)
03459         return FALSE;   
03460 
03461     // In order to find out whether or not we need to tell the processor whether or not to
03462     // scale to line width we need to find the line width, get the scaling required to scale
03463     // to that value and compare it with the scaling that we want to do here.
03464     MILLIPOINT LineWidth = pAttrBrush->GetAppliedLineWidth();
03465     double Scaling = pPPB->GetScaleValue(LineWidth);
03466 
03467     if (Scaling != NewScaling)
03468         pPPB->SetScaleToLineWidth(FALSE);
03469     else
03470         pPPB->SetScaleToLineWidth(TRUE);
03471 
03472     // clear out our cached bounding rect as we are changing size
03473     pAttrBrush->ClearCachedRect();
03474 
03475 
03476     return pAttrBrush->SetScaling(NewScaling);
03477 }
03478 
03479 
03480 /********************************************************************************************
03481 
03482 >   BOOL ChangeBrushAction::ChangeScalingIncr(double NewScaling, AttrBrushType* pAttrBrush)
03483 
03484     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03485     Created:    18/11/99
03486     Inputs:     NewScaling - the value to set       
03487     Outputs:    pAttrBrush - the brush attribute to change
03488     Returns:    TRUE if successful, FALSE otherwise
03489     Purpose:    To set the brush scaling of this attribute node
03490     SeeAlso:    -
03491 
03492 ********************************************************************************************/
03493 
03494 BOOL ChangeBrushAction::ChangeScalingIncr(double NewIncr, AttrBrushType* pAttrBrush)
03495 {
03496     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03497 
03498     // clear out our cached bounding rect as we are changing size
03499     pAttrBrush->ClearCachedRect();
03500 
03501 
03502     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03503     if (pPPB == NULL)
03504         return FALSE;   
03505 
03506     return pPPB->SetBrushScalingIncr(NewIncr);
03507 }
03508 
03509 
03510 /********************************************************************************************
03511 
03512 >   BOOL ChangeBrushAction::ChangeScalingIncrConst(double Incr, AttrBrushType* pAttrBrush)
03513 
03514     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03515     Created:    18/11/99
03516     Inputs:     Incr - the increment to set 
03517     Outputs:    pAttrBrush - the brush attribute to change
03518     Returns:    TRUE if successful, FALSE otherwise
03519     Purpose:    To set the brush scaling increment
03520     SeeAlso:    -
03521 
03522 ********************************************************************************************/
03523 
03524 BOOL ChangeBrushAction::ChangeScalingIncrConst(double Incr, AttrBrushType* pAttrBrush)
03525 {
03526     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03527 
03528     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03529     if (pPPB == NULL)
03530         return FALSE;   
03531 
03532     return pPPB->SetBrushScalingIncrConst(Incr);
03533 }
03534 
03535 /********************************************************************************************
03536 
03537 >   BOOL ChangeBrushAction::ChangeScalingMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03538 
03539     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03540     Created:    18/11/99
03541     Inputs:     NewMax - the value to set       
03542     Outputs:    pAttrBrush - the brush attribute to change
03543     Returns:    TRUE if successful, FALSE otherwise
03544     Purpose:    To set the amount of brush scaling determined by randomness
03545     SeeAlso:    -
03546 
03547 ********************************************************************************************/
03548 
03549 BOOL ChangeBrushAction::ChangeScalingMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03550 {
03551     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03552 
03553     // clear out our cached bounding rect as we are changing size
03554     pAttrBrush->ClearCachedRect();
03555 
03556 
03557     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03558     if (pPPB == NULL)
03559         return FALSE;   
03560 
03561     return pPPB->SetScalingMaxRand(NewMax);
03562 }
03563 
03564 
03565 /********************************************************************************************
03566 
03567 >   BOOL ChangeBrushAction::ChangeScalingMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03568 
03569     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03570     Created:    18/11/99
03571     Inputs:     NewMax - the value to set       
03572     Outputs:    pAttrBrush - the brush attribute to change
03573     Returns:    TRUE if successful, FALSE otherwise
03574     Purpose:    To set the amount of brush scaling determined by randomness
03575     SeeAlso:    -
03576 
03577 ********************************************************************************************/
03578 
03579 BOOL ChangeBrushAction::ChangeScalingPressure(UINT32 Pressure, AttrBrushType* pAttrBrush)
03580 {
03581     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03582 
03583     // clear out our cached bounding rect as we are changing size
03584     pAttrBrush->ClearCachedRect();
03585 
03586 
03587     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03588     if (pPPB == NULL)
03589         return FALSE;   
03590     
03591     return pPPB->SetScalingMaxPressure(Pressure);
03592 }
03593 /********************************************************************************************
03594 
03595 >   BOOL ChangeBrushAction::ChangeScalingRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
03596 
03597     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03598     Created:    18/11/99
03599     Inputs:     NewSeed - the value to set      
03600     Outputs:    pAttrBrush - the brush attribute to change
03601     Returns:    TRUE if successful, FALSE otherwise
03602     Purpose:    Sets a new seed for the scaling RNG
03603     SeeAlso:    -
03604 
03605 ********************************************************************************************/
03606 
03607 BOOL ChangeBrushAction::ChangeScalingRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
03608 {
03609     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03610 
03611     // clear out our cached bounding rect as we are changing size
03612     pAttrBrush->ClearCachedRect();
03613 
03614 
03615     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03616     if (pPPB == NULL)
03617         return FALSE;   
03618 
03619     return pPPB->SetScalingRandSeed(NewSeed);
03620 }
03621 
03622 /********************************************************************************************
03623 
03624 >   BOOL ChangeBrushAction::Rotation(double NewAngle, AttrBrushType* pAttrBrush)
03625     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03626     Created:    18/11/99
03627     Inputs:     NewAngle - the value to set     
03628     Outputs:    pAttrBrush - the brush attribute to change
03629     Returns:    TRUE if successful, FALSE otherwise
03630     Purpose:    To set the brush scaling of this attribute node
03631     SeeAlso:    -
03632 
03633 ********************************************************************************************/
03634 
03635 BOOL ChangeBrushAction::ChangeRotation(double NewAngle, AttrBrushType* pAttrBrush)
03636 {
03637     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03638 
03639     // clear out our cached bounding rect as we are changing size
03640     pAttrBrush->ClearCachedRect();
03641 
03642     return pAttrBrush->SetRotateAngle(NewAngle);
03643 }
03644 
03645 
03646 /********************************************************************************************
03647 
03648 >   BOOL ChangeBrushAction::ChangeRotationIncrProp(double Incr, AttrBrushType* pAttrBrush)
03649     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03650     Created:    18/11/99
03651     Inputs:     Incr - the value to set     
03652     Outputs:    pAttrBrush - the brush attribute to change
03653     Returns:    TRUE if successful, FALSE otherwise
03654     Purpose:    To set the rotation multiplier for this brush
03655     SeeAlso:    -
03656 
03657 ********************************************************************************************/
03658 
03659 BOOL ChangeBrushAction::ChangeRotationIncrProp(double Incr, AttrBrushType* pAttrBrush)
03660 {
03661     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03662     
03663     // clear out our cached bounding rect as we are changing size
03664     pAttrBrush->ClearCachedRect();
03665 
03666     // get the path processor
03667     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03668     if (pPPB == NULL)
03669         return FALSE;   
03670 
03671     return pPPB->SetRotationIncrProp(Incr);
03672 }
03673 
03674 
03675 /********************************************************************************************
03676 
03677 >   BOOL ChangeBrushAction::ChangeRotationIncrConst(double Incr, AttrBrushType* pAttrBrush)
03678     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03679     Created:    18/11/99
03680     Inputs:     Incr - the value to set     
03681     Outputs:    pAttrBrush - the brush attribute to change
03682     Returns:    TRUE if successful, FALSE otherwise
03683     Purpose:    To set the rotation increment for this brush
03684     SeeAlso:    -
03685 
03686 ********************************************************************************************/
03687 
03688 BOOL ChangeBrushAction::ChangeRotationIncrConst(double Incr, AttrBrushType* pAttrBrush)
03689 {
03690     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03691     
03692     // clear out our cached bounding rect as we are changing size
03693     pAttrBrush->ClearCachedRect();
03694 
03695     // get the path processor
03696     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03697     if (pPPB == NULL)
03698         return FALSE;   
03699 
03700     return pPPB->SetRotationIncrConst(Incr);
03701 }
03702 
03703 
03704 /********************************************************************************************
03705 
03706 >   BOOL ChangeBrushAction::ChangeRotationMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03707     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03708     Created:    18/11/99
03709     Inputs:     NewMax - the value to set       
03710     Outputs:    pAttrBrush - the brush attribute to change
03711     Returns:    TRUE if successful, FALSE otherwise
03712     Purpose:    To set the maximum random effect on the rotation of this brush
03713     SeeAlso:    -
03714 
03715 ********************************************************************************************/
03716 
03717 BOOL ChangeBrushAction::ChangeRotationMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03718 {
03719     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03720     
03721     // clear out our cached bounding rect as we are changing size
03722     pAttrBrush->ClearCachedRect();
03723 
03724     // get the path processor
03725     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03726     if (pPPB == NULL)
03727         return FALSE;   
03728 
03729     return pPPB->SetRotationMaxRand(NewMax);
03730 }
03731 
03732 
03733 /********************************************************************************************
03734 
03735 >   BOOL ChangeBrushAction::ChangeRotationRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
03736     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03737     Created:    18/11/99
03738     Inputs:     NewSeed - the value to set      
03739     Outputs:    pAttrBrush - the brush attribute to change
03740     Returns:    TRUE if successful, FALSE otherwise
03741     Purpose:    To set the seed for the rotation random number generator
03742     SeeAlso:    -
03743 
03744 ********************************************************************************************/
03745 
03746 BOOL ChangeBrushAction::ChangeRotationRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
03747 {
03748     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03749     
03750     // clear out our cached bounding rect as we are changing size
03751     pAttrBrush->ClearCachedRect();
03752 
03753     // get the path processor
03754     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03755     if (pPPB == NULL)
03756         return FALSE;   
03757 
03758     pPPB->SetRotationRandSeed(NewSeed);
03759 
03760     return TRUE;
03761 }
03762 
03763 
03764 /********************************************************************************************
03765 
03766 >   BOOL ChangeBrushAction::ChangeRotationMaxPressure(UINT32 Pressure, AttrBrushType* pAttrBrush)
03767     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03768     Created:    18/11/99
03769     Inputs:     Pressure - the value to set     
03770     Outputs:    pAttrBrush - the brush attribute to change
03771     Returns:    TRUE if successful, FALSE otherwise
03772     Purpose:    To set the sensitivity that rotation will have to pressure
03773     SeeAlso:    -
03774 
03775 ********************************************************************************************/
03776 
03777 BOOL ChangeBrushAction::ChangeRotationMaxPressure(UINT32 Pressure, AttrBrushType* pAttrBrush)
03778 {
03779     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03780     
03781     // clear out our cached bounding rect as we are changing size
03782     pAttrBrush->ClearCachedRect();
03783 
03784     // get the path processor
03785     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03786     if (pPPB == NULL)
03787         return FALSE;   
03788 
03789     return pPPB->SetRotationMaxPressure(Pressure);
03790 }
03791 
03792 /********************************************************************************************
03793 
03794 >   BOOL ChangeBrushAction::ChangeTiled(BOOL bTile, AttrBrushType* pAttrBrush)
03795     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03796     Created:    18/11/99
03797     Inputs:     bTile, to tile, or not  
03798     Outputs:    pAttrBrush - the brush attribute to change
03799     Returns:    TRUE if successful, FALSE otherwise
03800     Purpose:    To set the tiling of this attribute node
03801     SeeAlso:    -
03802 
03803 ********************************************************************************************/
03804 BOOL ChangeBrushAction::ChangeBrushTile(BOOL bTile, AttrBrushType* pAttrBrush)
03805 {
03806     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03807     return pAttrBrush->SetTiled(bTile);
03808 }
03809 
03810 
03811 /********************************************************************************************
03812 
03813 >   BOOL ChangeBrushAction::ChangeTangential(BOOL bRotate, AttrBrushType* pAttrBrush)
03814     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03815     Created:    18/11/99
03816     Inputs:     bTile, to tile, or not  
03817     Outputs:    pAttrBrush - the brush attribute to change
03818     Returns:    TRUE if successful, FALSE otherwise
03819     Purpose:    To set the tiling of this attribute node
03820     SeeAlso:    -
03821 
03822 ********************************************************************************************/
03823 
03824 BOOL ChangeBrushAction::ChangeTangential(BOOL bRotate, AttrBrushType* pAttrBrush)
03825 {
03826     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03827 
03828     // clear out our cached bounding rect as we are changing size
03829     pAttrBrush->ClearCachedRect();
03830 
03831     
03832     return pAttrBrush->SetRotated(bRotate);
03833 }
03834 
03835 
03836 /********************************************************************************************
03837 
03838 >   BOOL ChangeBrushAction::ChangeOffsetValue(MILLIPOINT NewOfdfset, AttrBrushType* pAttrBrush)
03839 
03840     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03841     Created:    18/11/99
03842     Inputs:     NewOffset - the value to set        
03843     Outputs:    pAttrBrush - the brush attribute to change
03844     Returns:    TRUE if successful, FALSE otherwise
03845     Purpose:    To set the offset value of this attribute node
03846     SeeAlso:    -
03847 
03848 ********************************************************************************************/
03849 
03850 BOOL ChangeBrushAction::ChangeOffsetValue(MILLIPOINT NewOffset, AttrBrushType* pAttrBrush)
03851 {
03852     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03853     
03854     // clear out our cached bounding rect as we are changing size
03855     pAttrBrush->ClearCachedRect();
03856     
03857     return pAttrBrush->SetPathOffsetValue(NewOffset);
03858 }
03859 
03860 
03861 /********************************************************************************************
03862 
03863 >   BOOL ChangeBrushAction::ChangeOffsetIncrProp(double NewIncrProp, AttrBrushType* pAttrBrush)
03864 
03865     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03866     Created:    18/11/99
03867     Inputs:     NewIncrProp - the value to set      
03868     Outputs:    pAttrBrush - the brush attribute to change
03869     Returns:    TRUE if successful, FALSE otherwise
03870     Purpose:    To set the offset value of this attribute node
03871     SeeAlso:    -
03872 
03873 ********************************************************************************************/
03874 
03875 BOOL ChangeBrushAction::ChangeOffsetIncrProp(double NewIncrProp, AttrBrushType* pAttrBrush)
03876 {
03877     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03878     
03879     // clear out our cached bounding rect as we are changing size
03880     pAttrBrush->ClearCachedRect();
03881 
03882     // get the path processor
03883     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03884     if (pPPB == NULL)
03885         return FALSE;   
03886 
03887     return pPPB->SetPathOffsetIncrProp(NewIncrProp);
03888 }
03889 
03890 
03891 
03892 /********************************************************************************************
03893 
03894 >   BOOL ChangeBrushAction::ChangeOffsetIncrConst(MILLIPOINT NewIncr, AttrBrushType* pAttrBrush)
03895 
03896     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03897     Created:    18/11/99
03898     Inputs:     NewIncrProp - the value to set      
03899     Outputs:    pAttrBrush - the brush attribute to change
03900     Returns:    TRUE if successful, FALSE otherwise
03901     Purpose:    To set the offset value of this attribute node
03902     SeeAlso:    -
03903 
03904 ********************************************************************************************/
03905 
03906 BOOL ChangeBrushAction::ChangeOffsetIncrConst(MILLIPOINT NewIncrConst, AttrBrushType* pAttrBrush)
03907 {
03908     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03909     
03910     // clear out our cached bounding rect as we are changing size
03911     pAttrBrush->ClearCachedRect();
03912 
03913     // get the path processor
03914     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03915     if (pPPB == NULL)
03916         return FALSE;   
03917 
03918     return pPPB->SetPathOffsetIncrConst(NewIncrConst);
03919 }
03920 
03921 
03922 
03923 /********************************************************************************************
03924 
03925 >   BOOL ChangeBrushAction::ChangeOffsetValMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03926 
03927     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03928     Created:    18/11/99
03929     Inputs:     NewMax - the value to set       
03930     Outputs:    pAttrBrush - the brush attribute to change
03931     Returns:    TRUE if successful, FALSE otherwise
03932     Purpose:    To set how much the offset is determined randomly
03933     SeeAlso:    -
03934 
03935 ********************************************************************************************/
03936 
03937 BOOL ChangeBrushAction::ChangeOffsetValMaxRand(UINT32 NewMax, AttrBrushType* pAttrBrush)
03938 {
03939     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03940     
03941     // clear out our cached bounding rect as we are changing size
03942     pAttrBrush->ClearCachedRect();
03943 
03944     // get the path processor
03945     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03946     if (pPPB == NULL)
03947         return FALSE;   
03948 
03949     return pPPB->SetOffsetValueMaxRand(NewMax);
03950 }
03951 
03952 
03953 /********************************************************************************************
03954 
03955 >   BOOL ChangeBrushAction::ChangeOffsetValRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
03956 
03957     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03958     Created:    18/11/99
03959     Inputs:     NewSeed - the value to set      
03960     Outputs:    pAttrBrush - the brush attribute to change
03961     Returns:    TRUE if successful, FALSE otherwise
03962     Purpose:    To set the seed for the offset value RNG
03963     SeeAlso:    -
03964 
03965 ********************************************************************************************/
03966 
03967 BOOL ChangeBrushAction::ChangeOffsetValRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
03968 {
03969     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03970     
03971     // clear out our cached bounding rect as we are changing size
03972     pAttrBrush->ClearCachedRect();
03973 
03974     // get the path processor
03975     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
03976     if (pPPB == NULL)
03977         return FALSE;   
03978 
03979     return pPPB->SetOffsetValueRandSeed(NewSeed);
03980 }
03981 
03982 /********************************************************************************************
03983 
03984 >   BOOL ChangeBrushAction::ChangeOffsetType(PathOffset NewOffset, AttrBrushType* pAttrBrush)
03985 
03986     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
03987     Created:    18/11/99
03988     Inputs:     NewOffset - the offset type to set      
03989     Outputs:    pAttrBrush - the brush attribute to change
03990     Returns:    TRUE if successful, FALSE otherwise
03991     Purpose:    To set the offset value of this attribute node
03992     SeeAlso:    -
03993 
03994 ********************************************************************************************/
03995 
03996 BOOL ChangeBrushAction::ChangeOffsetType(PathOffset NewOffset, AttrBrushType* pAttrBrush)
03997 {
03998     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
03999         
04000     // clear out our cached bounding rect as we are changing size
04001     pAttrBrush->ClearCachedRect();
04002 
04003     return pAttrBrush->SetPathOffsetType(NewOffset);    
04004 }
04005 
04006 
04007 /********************************************************************************************
04008 
04009 >   BOOL ChangeBrushAction::ChangeOffsetTypeRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
04010 
04011     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04012     Created:    18/11/99
04013     Inputs:     NewSeed - the offset type to set        
04014     Outputs:    pAttrBrush - the brush attribute to change
04015     Returns:    TRUE if successful, FALSE otherwise
04016     Purpose:    Sets the seed for the offset type RNG
04017     SeeAlso:    -
04018 
04019 ********************************************************************************************/
04020 
04021 BOOL ChangeBrushAction::ChangeOffsetTypeSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
04022 {
04023     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04024 
04025     // clear out our cached bounding rect as we are changing size
04026     pAttrBrush->ClearCachedRect();
04027     // get the path processor
04028     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04029     if (pPPB == NULL)
04030         return FALSE;   
04031 
04032     return pPPB->SetOffsetTypeRandSeed(NewSeed);
04033 }
04034 
04035 
04036 
04037 /********************************************************************************************
04038 
04039 >   BOOL ChangeBrushAction::ChangeOffsetSeeds(UINT32 NewTypeSeed, UINT32 NewValSeed, 
04040                                                 AttrBrushType* pAttrBrush)
04041 
04042     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04043     Created:    18/11/99
04044     Inputs:     NewTypeSeed - the seed for the offset sequence
04045                 NewValSeed - the seed for the offset value
04046     Outputs:    pAttrBrush - the brush attribute to change
04047     Returns:    TRUE if successful, FALSE otherwise
04048     Purpose:    This sets both the offset random seeds, this enables us to change both seeds
04049                 with only one button on the infobar.
04050     SeeAlso:    -
04051 
04052 ********************************************************************************************/
04053 
04054 BOOL ChangeBrushAction::ChangeOffsetSeeds(UINT32 NewTypeSeed, UINT32 NewValSeed, AttrBrushType* pAttrBrush)
04055 {
04056     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04057 
04058     // clear out our cached bounding rect as we are changing size
04059     pAttrBrush->ClearCachedRect();  
04060 
04061     // get the path processor
04062     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04063     if (pPPB == NULL)
04064         return FALSE;
04065 
04066     pPPB->SetOffsetTypeRandSeed(NewTypeSeed);
04067     pPPB->SetOffsetValueRandSeed(NewValSeed);
04068 
04069     return TRUE;
04070 }
04071 
04072 /********************************************************************************************
04073 
04074 >   BOOL ChangeBrushAction::ChangeSpacingMaxRand(UINT32 MaxRand, AttrBrushType* pAttrBrush)
04075 
04076     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04077     Created:    18/11/99
04078     Inputs:     MaxRand - the new maximum random number
04079     Outputs:    pAttrBrush - the brush attribute to change
04080     Returns:    TRUE if successful, FALSE otherwise
04081     Purpose:    To set the maximum random value for spacing for this attribute node
04082     SeeAlso:    -
04083 
04084 ********************************************************************************************/
04085 
04086 BOOL ChangeBrushAction::ChangeSpacingMaxRand(UINT32 NewMaxRand, AttrBrushType* pAttrBrush)
04087 {
04088     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04089     
04090     // can't be bothered to write any more natty access fn's in the attribute
04091     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04092     if (pPPB == NULL)
04093         return FALSE;
04094     return pPPB->SetSpacingMaxRand(NewMaxRand);
04095 }
04096 
04097 
04098 /********************************************************************************************
04099 
04100 >   BOOL ChangeBrushAction::ChangeSpacingRandSeed(UINT32 RandSeed, AttrBrushType* pAttrBrush)
04101 
04102     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04103     Created:    18/11/99
04104     Inputs:     RandSeed - seed to use for random spacing
04105     Outputs:    pAttrBrush - the brush attribute to change
04106     Returns:    TRUE if successful, FALSE otherwise
04107     Purpose:    To set the random seed for spacing for this attribute node
04108     SeeAlso:    -
04109 
04110 ********************************************************************************************/
04111 
04112 BOOL ChangeBrushAction::ChangeSpacingRandSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
04113 {
04114     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04115     
04116     TRACEUSER( "Diccon", _T("Setting Random Seed\n"));
04117 
04118     // get the path processor
04119     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04120     if (pPPB == NULL)
04121         return FALSE;
04122 
04123     // ok now that the sequence tab is on the same page they have to share a button
04124     pPPB->SetSequenceSeed(NewSeed);
04125     return pPPB->SetSpacingRandSeed(NewSeed);
04126 }
04127 
04128 
04129 /********************************************************************************************
04130 
04131 >   BOOL ChangeBrushAction::ChangeUseLocalfillColour(BOOL UseLocal, AttrBrushType* pAttrBrush)
04132 
04133     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04134     Created:    18/11/99
04135     Inputs:     UseLocal - the flag to set
04136     Outputs:    pAttrBrush - the brush attribute to change
04137     Returns:    TRUE if successful, FALSE otherwise
04138     Purpose:    Sets the flag telling this attribute whether to use local attributes
04139     SeeAlso:    -
04140 
04141 ********************************************************************************************/
04142 
04143 BOOL ChangeBrushAction::ChangeUseLocalFillColour(BOOL bUseLocal, AttrBrushType* pAttrBrush)
04144 {
04145     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04146     
04147     // get the path processor
04148     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04149     if (pPPB == NULL)
04150         return FALSE;
04151     pPPB->SetUseLocalFillColour(bUseLocal);
04152     return TRUE;
04153 }
04154 
04155 
04156 /********************************************************************************************
04157 
04158 >   BOOL ChangeBrushAction::ChangeUseLocalTransp(BOOL UseLocal, AttrBrushType* pAttrBrush)
04159 
04160     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04161     Created:    18/11/99
04162     Inputs:     UseLocal - the flag to set
04163     Outputs:    pAttrBrush - the brush attribute to change
04164     Returns:    TRUE if successful, FALSE otherwise
04165     Purpose:    Sets the flag telling this attribute whether to use local attributes
04166     SeeAlso:    -
04167 
04168 ********************************************************************************************/
04169 
04170 BOOL ChangeBrushAction::ChangeUseLocalTransp(BOOL UseLocal, AttrBrushType* pAttrBrush)
04171 {
04172     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04173     
04174     // get the path processor
04175     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04176     if (pPPB == NULL)
04177         return FALSE;
04178     pPPB->SetUseLocalTransp(UseLocal);
04179     return TRUE;
04180 }
04181 
04182 
04183 /********************************************************************************************
04184 
04185 >   BOOL ChangeBrushAction::ChangeUseNamedColour(BOOL UseLocal, AttrBrushType* pAttrBrush)
04186 
04187     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04188     Created:    18/11/99
04189     Inputs:     UseLocal - the flag to set
04190     Outputs:    pAttrBrush - the brush attribute to change
04191     Returns:    TRUE if successful, FALSE otherwise
04192     Purpose:    Sets the flag telling this attribute whether to use local attributes
04193     SeeAlso:    -
04194 
04195 ********************************************************************************************/
04196 
04197 BOOL ChangeBrushAction::ChangeUseNamedColour(BOOL UseNamed, AttrBrushType* pAttrBrush)
04198 {
04199     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04200     
04201     // get the path processor
04202     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04203     if (pPPB == NULL)
04204         return FALSE;
04205     pPPB->SetUseNamedColours(UseNamed);
04206 
04207     return TRUE;
04208 }
04209 
04210 /********************************************************************************************
04211 
04212 >   BOOL ChangeBrushAction::ChangeSequenceType(SequenceType NewSeq, AttrBrushType* pAttrBrush)
04213 
04214     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04215     Created:    18/11/99
04216     Inputs:     NewSeq - the sequence type to set
04217     Outputs:    pAttrBrush - the brush attribute to change
04218     Returns:    TRUE if successful, FALSE otherwise
04219     Purpose:    Sets the flag telling this attribute what type of object sequence to use
04220     SeeAlso:    -
04221 
04222 ********************************************************************************************/
04223 
04224 BOOL ChangeBrushAction::ChangeSequenceType(SequenceType NewSeq, AttrBrushType* pAttrBrush)
04225 {
04226     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04227     
04228     // get the path processor
04229     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04230     if (pPPB == NULL)
04231         return FALSE;
04232 
04233     pPPB->SetSequenceType(NewSeq);
04234     return TRUE;
04235 }
04236 
04237 
04238 
04239 /********************************************************************************************
04240 
04241 >   BOOL ChangeBrushAction::ChangeSequenceType(UINT32 NewSeed, AttrBrushType* pAttrBrush)
04242 
04243     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04244     Created:    18/11/99
04245     Inputs:     NewSeed - the seed to set
04246     Outputs:    pAttrBrush - the brush attribute to change
04247     Returns:    TRUE if successful, FALSE otherwise
04248     Purpose:    Seeds the sequence random number generator
04249     SeeAlso:    -
04250 
04251 ********************************************************************************************/
04252 
04253 BOOL ChangeBrushAction::ChangeSequenceSeed(UINT32 NewSeed, AttrBrushType* pAttrBrush)
04254 {
04255     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04256     
04257     // get the path processor
04258     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04259     if (pPPB == NULL)
04260         return FALSE;
04261 
04262     pPPB->SetSequenceSeed(NewSeed);
04263     return TRUE;
04264 }
04265 
04266 
04267 /********************************************************************************************
04268 
04269 >   BOOL ChangeBrushAction::ChangeHueIncrement(
04270     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04271     Created:    18/11/99
04272     Inputs:     NewSeed - the seed to set
04273     Outputs:    pAttrBrush - the brush attribute to change
04274     Returns:    TRUE if successful, FALSE otherwise
04275     Purpose:    Seeds the sequence random number generator
04276     SeeAlso:    -
04277 
04278 ********************************************************************************************/
04279 
04280 BOOL ChangeBrushAction::ChangeHueIncrement(double NewIncr, AttrBrushType* pAttrBrush)
04281 {
04282     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04283     
04284     // get the path processor
04285     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04286     if (pPPB == NULL)
04287         return FALSE;
04288 
04289     return pPPB->SetHueIncrement(NewIncr);
04290 }
04291 
04292 
04293 /********************************************************************************************
04294 
04295 >   BOOL ChangeBrushAction::ChangeHueMaxRand(UINT32 Rand, AttrBrushType* pAttrBrush)
04296 
04297     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04298     Created:    18/11/99
04299     Inputs:     Rand - the maximum random effect on hue
04300     Outputs:    pAttrBrush - the brush attribute to change
04301     Returns:    TRUE if successful, FALSE otherwise
04302     Purpose:    as above
04303     SeeAlso:    -
04304 
04305 ********************************************************************************************/
04306 
04307 BOOL ChangeBrushAction::ChangeHueMaxRand(UINT32 Rand, AttrBrushType* pAttrBrush)
04308 {
04309     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04310     
04311     // get the path processor
04312     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04313     if (pPPB == NULL)
04314         return FALSE;
04315 
04316     return pPPB->SetHueMaxRand(Rand);
04317 }
04318 
04319 
04320 /********************************************************************************************
04321 
04322 >   BOOL ChangeBrushAction::ChangeHueRandSeed(UINT32 Seed, AttrBrushType* pAttrBrush)
04323 
04324     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04325     Created:    18/11/99
04326     Inputs:     Seed - the seed for the hue RNG
04327     Outputs:    pAttrBrush - the brush attribute to change
04328     Returns:    TRUE if successful, FALSE otherwise
04329     Purpose:    Seeds the sequence random number generator
04330     SeeAlso:    -
04331 
04332 ********************************************************************************************/
04333 
04334 BOOL ChangeBrushAction::ChangeFillSeeds(UINT32 HueSeed, UINT32 SatSeed, AttrBrushType* pAttrBrush)
04335 {
04336     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04337     
04338     // get the path processor
04339     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04340     if (pPPB == NULL)
04341         return FALSE;
04342 
04343     pPPB->SetHueRandSeed(HueSeed);
04344     pPPB->SetSatRandSeed(SatSeed);
04345     return TRUE;
04346 }
04347 
04348 
04349 /********************************************************************************************
04350 
04351 >   BOOL ChangeBrushAction::ChangeSatMaxRand(UINT32 Rand, AttrBrushType* pAttrBrush)
04352 
04353     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04354     Created:    18/11/99
04355     Inputs:     Rand - the maximum random effect on Saturation
04356     Outputs:    pAttrBrush - the brush attribute to change
04357     Returns:    TRUE if successful, FALSE otherwise
04358     Purpose:    sa above
04359     SeeAlso:    -
04360 
04361 ********************************************************************************************/
04362 
04363 BOOL ChangeBrushAction::ChangeSatMaxRand(UINT32 Rand, AttrBrushType* pAttrBrush)
04364 {
04365     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04366     
04367     // get the path processor
04368     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04369     if (pPPB == NULL)
04370         return FALSE;
04371 
04372     return pPPB->SetSatMaxRand(Rand);
04373 }
04374 
04375 
04376 /********************************************************************************************
04377 
04378 >   BOOL ChangeBrushAction::ChangeSatRandSeed(UINT32 Seed, AttrBrushType* pAttrBrush)
04379 
04380     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04381     Created:    18/11/99
04382     Inputs:     Seed - the seed for the Saturation RNG
04383     Outputs:    pAttrBrush - the brush attribute to change
04384     Returns:    TRUE if successful, FALSE otherwise
04385     Purpose:    Seeds the sequence random number generator
04386     SeeAlso:    -
04387 
04388 ********************************************************************************************/
04389 
04390 BOOL ChangeBrushAction::ChangeSatRandSeed(UINT32 Seed, AttrBrushType* pAttrBrush)
04391 {
04392     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04393     
04394     // get the path processor
04395     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04396     if (pPPB == NULL)
04397         return FALSE;
04398 
04399     return pPPB->SetSatRandSeed(Seed);
04400 }
04401 
04402 
04403 /********************************************************************************************
04404 
04405 >   BOOL ChangeBrushAction::ChangeTransparency(INT32 Transp, AttrBrushType* pAttrBrush)
04406 
04407     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04408     Created:    18/11/99
04409     Inputs:     Transp - the value to set (-1 means don't replace transparency)
04410     Outputs:    pAttrBrush - the brush attribute to change
04411     Returns:    TRUE if successful, FALSE otherwise
04412     Purpose:    sets the replacement transparency value
04413     SeeAlso:    -
04414 
04415 ********************************************************************************************/
04416 
04417 BOOL ChangeBrushAction::ChangeTransparency(INT32 Transp, AttrBrushType* pAttrBrush)
04418 {
04419     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04420     
04421     // get the path processor
04422     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04423     if (pPPB == NULL)
04424         return FALSE;
04425 
04426     return pPPB->SetBrushTransparency(Transp);
04427 }
04428 
04429 
04430 /********************************************************************************************
04431 
04432 >   BOOL ChangeBrushAction::ChangeTranspPressure(UINT32 Press, AttrBrushType* pAttrBrush)
04433 
04434     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04435     Created:    18/11/99
04436     Inputs:     Press - the extent to which pressure affects brush transparency
04437     Outputs:    pAttrBrush - the brush attribute to change
04438     Returns:    TRUE if successful, FALSE otherwise
04439     Purpose:    sets the extent to which pressure affects brush transparency
04440     SeeAlso:    -
04441 
04442 ********************************************************************************************/
04443 
04444 BOOL ChangeBrushAction::ChangeTranspPressure(UINT32 Press, AttrBrushType* pAttrBrush)
04445 {
04446     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL");
04447     
04448     // get the path processor
04449     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04450     if (pPPB == NULL)
04451         return FALSE;
04452 
04453     return pPPB->SetTransparencyPressure(Press);
04454 }
04455 
04456 
04457 /********************************************************************************************
04458 
04459 >   BOOL ChangeBrushAction::ChangeAll(ChangeBrushOpParam* pParam, AttrBrushType* pAttrBrush)
04460 
04461     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04462     Created:    18/11/99
04463     Inputs:     pParam - the opparam containing the data to change in our brush
04464     Outputs:    pAttrBrush - the brush attribute to change
04465     Returns:    TRUE if successful, FALSE otherwise
04466     Purpose:    Sets all the variables in the opparam
04467     SeeAlso:    -
04468 
04469 ********************************************************************************************/
04470 
04471 BOOL ChangeBrushAction::ChangeAll(ChangeBrushOpParam* pParam, AttrBrushType* pAttrBrush)
04472 {
04473     ERROR2IF(pAttrBrush == NULL, FALSE, "brush attribute is NULL in ChangeBrushAction::ChangeAll");
04474     ERROR2IF(pParam == NULL, FALSE, "OpParam is NULL in ChangeBrushAction::ChangeAll");
04475     // get the path processor
04476     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04477     if (pPPB == NULL)
04478         return FALSE;
04479     
04480     BOOL ok = pPPB->SetBrushScaling(pParam->m_NewScaling);
04481     if (ok) ok = pPPB->SetBrushScalingIncr(pParam->m_NewScalingIncr);
04482     if (ok) ok = pPPB->SetBrushScalingIncrConst(pParam->m_NewScalingIncrConst);
04483     if (ok) ok = pPPB->SetScalingMaxRand(pParam->m_NewScalingMaxRand);
04484     if (ok) ok = pPPB->SetScalingRandSeed(pParam->m_NewScalingRandSeed);
04485     if (ok) ok = pPPB->SetSpacing(pParam->m_NewSpacing);
04486     if (ok) ok = pPPB->SetSpacingIncrConst(pParam->m_NewSpacingIncrConst);
04487     if (ok) ok = pPPB->SetSpacingIncrProp(pParam->m_NewSpacingIncrProp);
04488     if (ok) ok = pPPB->SetSpacingMaxRand(pParam->m_NewSpacingMaxRand);
04489     if (ok) ok = pPPB->SetSpacingRandSeed(pParam->m_NewSpacingRandSeed);
04490     if (ok) ok = pPPB->SetHueMaxRand(pParam->m_NewHueMaxRand);
04491     if (ok) ok = pPPB->SetHueRandSeed(pParam->m_NewHueRandSeed);
04492     if (ok) ok = pPPB->SetSatMaxRand(pParam->m_NewSatMaxRand);
04493     if (ok) ok = pPPB->SetSatRandSeed(pParam->m_NewSatRandSeed);
04494     pPPB->SetPathOffsetType(pParam->m_NewPathOffsetType);
04495     pPPB->SetPathOffsetValue(pParam->m_NewPathOffsetVal);
04496     if (ok) ok = pPPB->SetOffsetTypeRandSeed(pParam->m_NewOffsetTypeRandSeed);
04497     if (ok) ok = pPPB->SetOffsetValueMaxRand(pParam->m_NewOffsetValMaxRand);
04498     if (ok) ok = pPPB->SetOffsetValueRandSeed(pParam->m_NewOffsetValRandSeed);
04499     pPPB->SetRotated(pParam->m_bNewTiled);
04500     if (ok) ok = pPPB->SetRotationAngle(pParam->m_NewRotateAngle);
04501     pPPB->SetSequenceType(pParam->m_NewSequenceType);
04502     pPPB->SetSequenceSeed(pParam->m_NewSequenceRandSeed);
04503     pPPB->SetTiling(pParam->m_bNewTiled);
04504     pPPB->SetUseLocalFillColour(pParam->m_bNewUseLocalFillColour);
04505     pPPB->SetRotationIncrConst(pParam->m_NewRotationIncrConst);
04506     pPPB->SetRotationIncrProp(pParam->m_NewRotationIncrProp);
04507     pPPB->SetRotationMaxPressure(pParam->m_NewRotationMaxPressure);
04508 
04509     return ok;
04510 }
04511 
04512 
04513 
04514 //-------------------------------------------------------
04515 //------------CLASS CHANGEBRUSHOPPARAM-------------------
04516 //-------------------------------------------------------
04517 
04518 
04519 /********************************************************************************************
04520 
04521 >   ChangeBrushOpParam::ChangeBrushOpParam()
04522 
04523     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04524     Created:    20/3/95
04525     Inputs:     -
04526     Outputs:    -
04527     Returns:    -
04528     Purpose:    default contructor 
04529     Errors:     -
04530 
04531 ********************************************************************************************/
04532 
04533 ChangeBrushOpParam::ChangeBrushOpParam()
04534 {
04535     InitMembers();
04536 }
04537 
04538 /********************************************************************************************
04539 
04540 >   ChangeBrushOpParam::ChangeBrushOpParam(const ChangeBrushOpParam& Other)
04541 
04542     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04543     Created:    20/3/95
04544     Inputs:     Other the ChangeBrushOpParam whose values we wish to assign
04545     Outputs:    -
04546     Returns:    -
04547     Purpose:    copy constructor
04548     Errors:     -
04549 
04550 ********************************************************************************************/
04551 
04552 ChangeBrushOpParam::ChangeBrushOpParam(const ChangeBrushOpParam& Other)
04553 {
04554 
04555 }
04556 
04557 
04558 /********************************************************************************************
04559 
04560 >   void ChangeBrushOpParam::InitMembers()
04561 
04562     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04563     Created:    20/3/95
04564     Inputs:     -
04565     Outputs:    -
04566     Returns:    -
04567     Purpose:    initialise our numerous members to something sensible
04568     Errors:     -
04569 
04570 ********************************************************************************************/
04571 
04572 void ChangeBrushOpParam::InitMembers()
04573 {
04574     ChangeType = CHANGEBRUSH_NONE;
04575 
04576     m_NewSpacing = m_OldSpacing = 10000;
04577     m_NewSpacingIncrProp = m_OldSpacingIncrProp = 1.0;
04578     m_NewSpacingIncrConst = m_OldSpacingIncrConst = 0;
04579     m_pPressure = NULL;
04580     m_OldSpacingMaxRand = m_NewSpacingMaxRand = 0;
04581     m_NewSpacingRandSeed = m_OldSpacingRandSeed = 0;
04582     m_OldScaling = m_NewScaling = 1.0;
04583     m_NewScalingIncr = m_OldScalingIncr = 1.0;
04584     m_NewScalingIncrConst = m_OldScalingIncrConst = 0;
04585     m_NewScalingMaxRand = m_OldScalingMaxRand = 0;
04586     m_NewScalingRandSeed = m_OldScalingRandSeed = 0;
04587     m_OldScalingMaxPressure = m_NewScalingMaxPressure = 0;
04588     m_OldPathOffsetType = m_NewPathOffsetType = OFFSET_NONE;
04589     m_NewOffsetTypeRandSeed = m_OldOffsetTypeRandSeed = 0;
04590     m_OldPathOffsetVal = m_NewPathOffsetVal = 0;
04591     m_NewOffsetIncrProp = m_OldOffsetIncrProp = 1.0;
04592     m_NewOffsetIncrConst = m_OldOffsetIncrConst = 0;
04593     m_NewOffsetValMaxRand = m_OldOffsetValMaxRand = 0;
04594     m_NewOffsetValRandSeed = m_OldOffsetValRandSeed = 0;
04595     m_bOldTiled = m_bNewTiled = TRUE;
04596     m_bOldRotated = m_bNewRotated = FALSE;
04597     m_OldRotateAngle = m_NewRotateAngle = 0.0;
04598     m_OldRotationIncrProp = m_NewRotationIncrProp = 1.0;
04599     m_OldRotationIncrConst = m_NewRotationIncrConst = 0.0;
04600     m_NewRotateMaxRand = m_OldRotateMaxRand = 0;
04601     m_NewRotateRandSeed = m_OldRotateRandSeed = 0;
04602     m_NewRotationMaxPressure = m_OldRotationMaxPressure = 0;
04603     m_OldBrushName = m_NewBrushName = TEXT("Custom Brush");
04604     m_bOldUseLocalFillColour = m_bNewUseLocalFillColour = FALSE;
04605     m_bNewUseLocalTransp = m_bOldUseLocalTransp = FALSE;
04606     m_bOldUseNamed = m_bNewUseNamed = FALSE;
04607     m_OldSequenceType = m_NewSequenceType = SEQ_FORWARD;
04608     m_NewSequenceRandSeed = m_OldSequenceRandSeed = 0;
04609     m_NewHueIncrement = m_OldHueIncrement = 0;
04610     m_NewHueMaxRand = m_OldHueMaxRand = 0;
04611     m_NewHueRandSeed = m_OldHueRandSeed = 0;
04612     m_NewSatMaxRand = m_OldSatMaxRand = 0;
04613     m_NewSatRandSeed = m_OldSatRandSeed = 0;
04614     m_NewTransp = m_OldTransp = 100;
04615     m_NewTranspPressure = m_OldTranspPressure = 0;
04616 
04617     m_OldTimeStampValue = m_NewTimeStampValue = 50;
04618 
04619 
04620 
04621 }
04622 
04623 
04624 
04625 /********************************************************************************************
04626 
04627 >   BOOL ChangeBrushOpParam::ChangeLineWidth()
04628 
04629     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04630     Created:    20/3/95
04631     Inputs:     -
04632     Outputs:    -
04633     Returns:    TRUE if this op param will cause the line width pf a brush to change, FALSE
04634                 if not
04635     Purpose:    as above
04636     Errors:     -
04637 
04638 ********************************************************************************************/
04639 
04640 BOOL ChangeBrushOpParam::ChangeLineWidth()
04641 {
04642     // see what type we are
04643     BOOL Retval = FALSE;
04644     
04645     switch (ChangeType)
04646     {
04647         // these types of changes will cause the line width to change
04648         case CHANGEBRUSH_SCALING_MAXRAND:
04649         case CHANGEBRUSH_SCALING_RANDSEED:
04650         case CHANGEBRUSH_OFFSET_TYPE:
04651         case CHANGEBRUSH_OFFSET_VAL:
04652         case CHANGEBRUSH_OFFSET_MAXRAND:
04653         case CHANGEBRUSH_TANGENTIAL:
04654         case CHANGEBRUSH_ROTATE_ANGLE:
04655         case CHANGEBRUSH_ROTATE_INCRCONST:
04656         case CHANGEBRUSH_ROTATE_MAXRAND:
04657         case CHANGEBRUSH_ALL:
04658             Retval = TRUE;
04659         break;
04660 
04661         default: // do nothing
04662         break;
04663     }
04664 
04665     return Retval;
04666 
04667 }
04668 
04669 /********************************************************************************************
04670 
04671 >   ChangeBrushOpParam ChangeBrushOpParam::operator=(const ChangeBrushOpParam& Other)
04672 
04673     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04674     Created:    20/3/95
04675     Inputs:     Other the ChangeBrushOpParam whose values we wish to assign
04676     Outputs:    -
04677     Returns:    -
04678     Purpose:    overrides assignment operator
04679     Errors:     -
04680 
04681 ********************************************************************************************/
04682 
04683 ChangeBrushOpParam ChangeBrushOpParam::operator=(const ChangeBrushOpParam& Other)
04684 {
04685     m_OldSpacing = Other.m_OldSpacing;
04686     m_NewSpacing = Other.m_NewSpacing;
04687     m_NewSpacingIncrProp = Other.m_NewSpacingIncrProp;
04688     m_OldSpacingIncrProp = Other.m_OldSpacingIncrProp;
04689     m_NewSpacingIncrConst = Other.m_NewSpacingIncrConst;
04690     m_OldSpacingIncrConst = Other.m_OldSpacingIncrConst;
04691     m_OldSpacingMaxRand = Other.m_OldSpacingMaxRand;
04692     m_NewSpacingMaxRand = Other.m_NewSpacingMaxRand;
04693     m_NewSpacingRandSeed = Other.m_NewSpacingRandSeed;
04694     m_OldSpacingRandSeed = Other.m_OldSpacingRandSeed;
04695     m_OldScaling = Other.m_OldScaling;
04696     m_NewScaling = Other.m_NewScaling;
04697     m_NewScalingIncr = Other.m_NewScalingIncr;
04698     m_OldScalingIncr = Other.m_OldScalingIncr;
04699     m_NewScalingIncrConst = Other.m_NewScalingIncrConst;
04700     m_OldScalingIncrConst = Other.m_OldScalingIncrConst;
04701     m_NewScalingMaxRand = Other.m_NewScalingMaxRand;
04702     m_OldScalingMaxRand = Other.m_OldScalingMaxRand;
04703     m_NewScalingRandSeed = Other.m_NewScalingRandSeed;
04704     m_OldScalingRandSeed = Other.m_OldScalingRandSeed;
04705     m_NewScalingMaxPressure = Other.m_NewScalingMaxPressure;
04706     m_OldScalingMaxPressure = Other.m_OldScalingMaxPressure;
04707     m_OldPathOffsetType = Other.m_OldPathOffsetType;
04708     m_NewPathOffsetType = Other.m_NewPathOffsetType;
04709     m_NewOffsetTypeRandSeed = Other.m_NewOffsetTypeRandSeed;
04710     m_OldOffsetTypeRandSeed = Other.m_OldOffsetTypeRandSeed;
04711     m_OldPathOffsetVal = Other.m_OldPathOffsetVal;
04712     m_NewPathOffsetVal = Other.m_NewPathOffsetVal;
04713     m_NewOffsetIncrProp = Other.m_NewOffsetIncrProp;
04714     m_OldOffsetIncrProp = Other.m_OldOffsetIncrProp;
04715     m_NewOffsetIncrConst = Other.m_NewOffsetIncrConst;
04716     m_OldOffsetIncrConst = Other.m_OldOffsetIncrConst;
04717     m_NewOffsetValMaxRand = Other.m_NewOffsetValMaxRand;
04718     m_OldOffsetValMaxRand = Other.m_OldOffsetValMaxRand;
04719     m_NewOffsetValRandSeed = Other.m_NewOffsetValRandSeed;
04720     m_OldOffsetValRandSeed = Other.m_OldOffsetValRandSeed;
04721     m_bOldTiled = Other.m_bOldTiled;
04722     m_bNewTiled = Other.m_bNewTiled;
04723     m_bOldRotated = Other.m_bOldRotated;
04724     m_bNewRotated = Other.m_bNewRotated;
04725     m_OldRotateAngle = Other.m_OldRotateAngle;
04726     m_NewRotateAngle = Other.m_NewRotateAngle;
04727     m_OldRotationIncrProp = Other.m_OldRotationIncrProp;
04728     m_NewRotationIncrProp = Other.m_NewRotationIncrProp;
04729     m_OldRotationIncrConst = Other.m_NewRotationIncrConst;
04730     m_NewRotationIncrConst = Other.m_NewRotationIncrConst;
04731     m_NewRotateMaxRand = Other.m_NewRotateMaxRand;
04732     m_OldRotateMaxRand = Other.m_OldRotateMaxRand;
04733     m_NewRotateRandSeed = Other.m_NewRotateRandSeed;
04734     m_OldRotateRandSeed = Other.m_OldRotateRandSeed;
04735     m_NewRotationMaxPressure = Other.m_NewRotationMaxPressure;
04736     m_OldBrushName = Other.m_OldBrushName;
04737     m_NewBrushName = Other.m_NewBrushName;
04738     m_bOldUseLocalFillColour = Other.m_bOldUseLocalFillColour;
04739     m_bNewUseLocalFillColour = Other.m_bNewUseLocalFillColour;
04740     m_bOldUseLocalTransp     = Other.m_bOldUseLocalTransp;
04741     m_bNewUseLocalTransp     = Other.m_bNewUseLocalTransp;
04742     m_OldSequenceType = Other.m_OldSequenceType;
04743     m_NewSequenceType = Other.m_NewSequenceType;
04744     m_NewSequenceRandSeed = Other.m_NewSequenceRandSeed;
04745     m_OldSequenceRandSeed = Other.m_OldSequenceRandSeed;
04746     m_NewTimeStampValue = Other.m_NewTimeStampValue;
04747     m_OldTimeStampValue = Other.m_OldTimeStampValue;
04748     m_bOldUseNamed = Other.m_bOldUseNamed;
04749     m_bNewUseNamed = Other.m_bNewUseNamed;
04750     m_NewHueMaxRand = Other.m_NewHueMaxRand;
04751     m_OldHueMaxRand = Other.m_OldHueMaxRand;
04752     m_NewHueRandSeed = Other.m_NewHueRandSeed;
04753     m_OldHueRandSeed = Other.m_OldHueRandSeed;
04754     m_NewSatMaxRand = Other.m_NewSatMaxRand;
04755     m_OldSatMaxRand = Other.m_OldSatMaxRand;
04756     m_NewSatRandSeed = Other.m_NewSatRandSeed;
04757     m_OldSatRandSeed = Other.m_OldSatRandSeed;
04758     m_NewTransp      = Other.m_NewTransp;
04759     m_OldTransp      = Other.m_OldTransp;
04760     m_NewTranspPressure = Other.m_NewTranspPressure;
04761     m_OldTranspPressure = Other.m_OldTranspPressure;
04762     return *this;
04763 }
04764 
04765 /********************************************************************************************
04766 
04767 >   void ChangeBrushOpParam::SetOldValues(AttrBrushType* pAttrBrush)
04768 
04769     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04770     Created:    20/3/95
04771     Inputs:     pAttrBrush - pointer to brush attribute which is being changed
04772     Outputs:    -
04773     Returns:    -
04774     Purpose:    Copies the current state of the brush node into this classes Old member vars
04775     Errors:     -
04776 
04777 ********************************************************************************************/
04778 
04779 void ChangeBrushOpParam::SetOldValues(AttrBrushType* pAttrBrush)
04780 {
04781     if (pAttrBrush == NULL)
04782     {
04783         ERROR3("Attribute is NULL");
04784         return;
04785     }
04786     MILLIPOINT Value = pAttrBrush->GetSpacing();
04787     if (Value != -1)
04788         m_OldSpacing = Value;
04789     else
04790         m_OldSpacing = DEFAULT_BRUSH_SPACING;
04791 
04792     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04793     if (pPPB != NULL)
04794     {
04795         m_OldSpacingMaxRand   = pPPB->GetSpacingMaxRand();
04796         m_OldSpacingRandSeed  = pPPB->GetSpacingRandSeed();
04797         m_OldSpacingIncrProp  = pPPB->GetSpacingIncrProp();
04798         m_OldSpacingIncrConst = pPPB->GetSpacingIncrConst();
04799         m_OldScaling          = pPPB->GetBrushScaling();
04800         m_OldScalingIncr      = pPPB->GetBrushScalingIncr();
04801         m_OldScalingIncrConst = pPPB->GetBrushScalingIncrConst();
04802         m_OldScalingMaxPressure = pPPB->GetScalingMaxPressure();
04803         m_OldScalingMaxRand     = pPPB->GetScalingMaxRand();
04804         m_OldScalingRandSeed    = pPPB->GetScalingRandSeed();
04805         m_OldPathOffsetVal    = pPPB->GetPathOffsetValue();
04806         m_OldOffsetIncrProp   = pPPB->GetPathOffsetIncrProp();
04807         m_OldOffsetIncrConst  = pPPB->GetPathOffsetIncrConst();
04808         m_OldPathOffsetType   = pPPB->GetPathOffsetType();
04809         m_OldOffsetValMaxRand = pPPB->GetOffsetValueMaxRand();
04810         m_bOldTiled           = pPPB->IsTiled();
04811         m_bOldRotated         = pPPB->IsRotated();
04812         m_OldRotateAngle      = pPPB->GetRotationAngle();
04813         m_OldRotationIncrConst = pPPB->GetRotationIncrConst();
04814         m_OldRotationIncrProp  = pPPB->GetRotationIncrProp();
04815         m_OldRotationMaxPressure = pPPB->GetRotationMaxPressure();
04816         m_OldRotateMaxRand   = pPPB->GetRotationMaxRand();
04817         m_bOldUseLocalFillColour    = pPPB->GetUseLocalFillColour();
04818         m_bOldUseLocalTransp = pPPB->GetUseLocalTransp();
04819         m_OldOffsetTypeRandSeed = pPPB->GetOffsetTypeRandSeed();
04820         m_OldSequenceType       = pPPB->GetSequenceType();
04821         m_OldSequenceRandSeed   = pPPB->GetSequenceSeed();
04822         m_bOldUseNamed          = pPPB->GetUseNamedColours();
04823         m_OldHueMaxRand         = pPPB->GetHueMaxRand();
04824         m_OldHueRandSeed        = pPPB->GetHueRandSeed();
04825         m_OldSatMaxRand         = pPPB->GetSatMaxRand();
04826         m_OldSatRandSeed        = pPPB->GetSatRandSeed();
04827         m_OldTransp             = pPPB->GetBrushTransparency();
04828         m_OldTranspPressure     = pPPB->GetTransparencyPressure();
04829         
04830     }
04831     //m_pPressure = pAttrBrush->GetPressureCache();
04832 
04833 
04834 }
04835 
04836 
04837 /********************************************************************************************
04838 
04839 >   void ChangeBrushOpParam::SetNewValues(AttrBrushType* pAttrBrush)
04840 
04841     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04842     Created:    20/3/95
04843     Inputs:     pAttrBrush - the attribute being changed by the operation
04844     Outputs:    -
04845     Returns:    -
04846     Purpose:    Copies the current state of the brush node into this classes New member vars
04847     Errors:     -
04848 
04849 ********************************************************************************************/
04850 
04851 void ChangeBrushOpParam::SetNewValues(AttrBrushType* pAttrBrush)
04852 {
04853     if (pAttrBrush == NULL)
04854     {
04855         ERROR3("Attribute is NULL");
04856         return;
04857     }
04858     MILLIPOINT Value = pAttrBrush->GetSpacing();
04859     if (Value != -1)
04860         m_NewSpacing = Value;
04861     else
04862         m_NewSpacing = DEFAULT_BRUSH_SPACING;
04863 
04864     PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor();
04865     if (pPPB != NULL)
04866     {
04867         m_NewSpacingMaxRand     = pPPB->GetSpacingMaxRand();
04868         m_NewSpacingRandSeed    = pPPB->GetSpacingRandSeed();
04869         m_NewSpacingIncrProp    = pPPB->GetSpacingIncrProp();
04870         m_NewSpacingIncrConst   = pPPB->GetSpacingIncrConst();
04871         m_NewScaling            = pPPB->GetBrushScaling();
04872         m_NewScalingIncr        = pPPB->GetBrushScalingIncr();
04873         m_NewScalingIncrConst   = pPPB->GetBrushScalingIncrConst();
04874         m_NewScalingMaxPressure = pPPB->GetScalingMaxPressure();
04875         m_NewScalingMaxRand     = pPPB->GetScalingMaxRand();
04876         m_NewScalingRandSeed    = pPPB->GetScalingRandSeed();
04877         m_NewPathOffsetVal      = pPPB->GetPathOffsetValue();
04878         m_NewOffsetIncrProp     = pPPB->GetPathOffsetIncrProp();
04879         m_NewOffsetIncrConst    = pPPB->GetPathOffsetIncrConst();
04880         m_NewPathOffsetType     = pPPB->GetPathOffsetType();
04881         m_NewOffsetValMaxRand   = pPPB->GetOffsetValueMaxRand();
04882         m_bNewTiled             = pPPB->IsTiled();
04883         m_bNewRotated           = pPPB->IsRotated();
04884         m_NewRotateAngle        = pPPB->GetRotationAngle();
04885         m_NewRotationIncrConst  = pPPB->GetRotationIncrConst();
04886         m_NewRotationIncrProp   = pPPB->GetRotationIncrProp();
04887         m_NewRotateRandSeed     = pPPB->GetRotationRandSeed();
04888         m_NewRotateMaxRand      = pPPB->GetRotationMaxRand();
04889         m_NewRotationMaxPressure    = pPPB->GetRotationMaxPressure();
04890         m_bNewUseLocalFillColour   = pPPB->GetUseLocalFillColour();
04891         m_bNewUseLocalTransp    = pPPB->GetUseLocalTransp();
04892         m_NewOffsetTypeRandSeed = pPPB->GetOffsetTypeRandSeed();
04893         m_NewSequenceType       = pPPB->GetSequenceType();
04894         m_NewSequenceRandSeed   = pPPB->GetSequenceSeed();
04895         m_bNewUseNamed          = pPPB->GetUseNamedColours();
04896         m_NewHueMaxRand         = pPPB->GetHueMaxRand();
04897         m_NewHueRandSeed        = pPPB->GetHueRandSeed();
04898         m_NewSatMaxRand         = pPPB->GetSatMaxRand();
04899         m_NewSatRandSeed        = pPPB->GetSatRandSeed();
04900         m_NewTransp             = pPPB->GetBrushTransparency();
04901         m_NewTranspPressure     = pPPB->GetTransparencyPressure();
04902     }
04903 
04904 }
04905 
04906 /********************************************************************************************
04907 
04908 >   void ChangeBrushOpParam::SwapOldAndNew()
04909 
04910     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04911     Created:    18/11/99
04912     Inputs:     -
04913     Outputs:    -
04914     Returns:    -
04915     Purpose:    Swaps the old and new values of this class
04916     Errors:     -
04917 
04918 ********************************************************************************************/
04919 
04920 void ChangeBrushOpParam::SwapOldAndNew()
04921 {
04922     SwapINT32(m_OldSpacing, m_NewSpacing);
04923     SwapINT32( m_OldSpacingIncrConst, m_NewSpacingIncrConst);
04924     SwapDouble(m_OldSpacingIncrProp, m_NewSpacingIncrProp);
04925     SwapUINT( m_OldSpacingMaxRand, m_NewSpacingMaxRand);
04926     SwapUINT( m_OldSpacingRandSeed, m_NewSpacingRandSeed);
04927     SwapDouble(m_OldScaling, m_NewScaling);
04928     SwapDouble(m_OldScalingIncr, m_NewScalingIncr);
04929     SwapDouble(m_OldScalingIncrConst, m_NewScalingIncrConst);
04930     SwapUINT( m_OldScalingMaxRand, m_NewScalingMaxRand);
04931     SwapUINT( m_OldScalingRandSeed, m_NewScalingRandSeed);
04932     SwapUINT( m_OldScalingMaxPressure, m_NewScalingMaxPressure);
04933     
04934     // using this typedef in the macro seems to cause floating point errors in release builds
04935     PathOffset TempOffset = m_OldPathOffsetType;
04936     m_OldPathOffsetType = m_NewPathOffsetType;
04937     m_NewPathOffsetType = TempOffset;
04938 
04939     SwapUINT( m_OldOffsetTypeRandSeed, m_NewOffsetTypeRandSeed);
04940     SwapINT32( m_OldPathOffsetVal, m_NewPathOffsetVal);
04941     SwapINT32( m_OldOffsetIncrConst, m_NewOffsetIncrConst);
04942     SwapDouble(m_OldOffsetIncrProp, m_NewOffsetIncrProp);
04943     SwapUINT( m_OldOffsetValMaxRand, m_NewOffsetValMaxRand);
04944     SwapUINT( m_OldOffsetValRandSeed, m_NewOffsetValRandSeed);
04945     SwapBOOL(m_bOldTiled, m_bNewTiled);
04946     SwapBOOL(m_bOldRotated, m_bNewRotated);
04947     SwapDouble(m_OldRotateAngle, m_NewRotateAngle);
04948     SwapDouble(m_OldRotationIncrProp, m_NewRotationIncrProp);
04949     SwapDouble(m_OldRotationIncrConst, m_NewRotationIncrConst);
04950     SwapUINT( m_OldRotateMaxRand, m_NewRotateMaxRand);
04951     SwapUINT( m_OldRotateRandSeed, m_NewRotateRandSeed);
04952     SwapUINT( m_OldRotationMaxPressure, m_NewRotationMaxPressure);
04953     SwapBOOL(m_bOldUseLocalFillColour, m_bNewUseLocalFillColour);
04954     SwapBOOL(m_bOldUseLocalTransp, m_bNewUseLocalTransp);
04955     SequenceType Temp = m_OldSequenceType;
04956     m_OldSequenceType = m_NewSequenceType;
04957     m_NewSequenceType = Temp;
04958     SwapUINT( m_OldSequenceRandSeed, m_NewSequenceRandSeed);
04959     SwapBOOL(m_bOldUseNamed, m_bNewUseNamed);
04960     SwapUINT( m_OldHueMaxRand, m_NewHueMaxRand);
04961     SwapUINT( m_OldHueRandSeed, m_NewHueRandSeed);
04962     SwapUINT( m_OldSatMaxRand, m_NewSatMaxRand);
04963     SwapUINT( m_OldSatRandSeed, m_NewSatRandSeed);
04964     SwapINT32( m_OldTransp, m_NewTransp);
04965     SwapUINT( m_OldTranspPressure, m_NewTranspPressure);
04966 }
04967 
04968 
04969 /********************************************************************************************
04970 
04971 >   void ChangeBrushOpParam::SwapDouble(double& First, double& Second)
04972     
04973     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04974     Created:    18/11/99
04975     Inputs:     First - the first value
04976                 Second - the value to swap with
04977     Outputs:    -
04978     Returns:    -
04979     Purpose:    Swaps the two double values
04980     Errors:     -
04981 
04982 ********************************************************************************************/
04983 
04984 void ChangeBrushOpParam::SwapDouble(double& First, double& Second)
04985 {
04986     double Temp = First;
04987     First = Second;
04988     Second = Temp;
04989 }
04990 
04991 
04992 /********************************************************************************************
04993 
04994 >   void ChangeBrushOpParam::SwapUINT(UINT32& First, UINT32& Second)
04995     
04996     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
04997     Created:    18/11/99
04998     Inputs:     First - the first value
04999                 Second - the value to swap with
05000     Outputs:    -
05001     Returns:    -
05002     Purpose:    Swaps the two UINT32 values
05003     Errors:     -
05004 
05005 ********************************************************************************************/
05006 
05007 void ChangeBrushOpParam::SwapUINT(UINT32& First, UINT32& Second)
05008 {
05009     UINT32 Temp = First;
05010     First = Second;
05011     Second = Temp;
05012 }
05013 
05014 
05015 /********************************************************************************************
05016 
05017 >   void ChangeBrushOpParam::SwapINT32(INT32& First, INT32& Second)
05018     
05019     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05020     Created:    18/11/99
05021     Inputs:     First - the first value
05022                 Second - the value to swap with
05023     Outputs:    -
05024     Returns:    -
05025     Purpose:    Swaps the two INT32 values
05026     Errors:     -
05027 
05028 ********************************************************************************************/
05029 
05030 void ChangeBrushOpParam::SwapINT32(INT32& First, INT32& Second)
05031 {
05032     INT32 Temp = First;
05033     First = Second;
05034     Second = Temp;
05035 }
05036 
05037 
05038 /********************************************************************************************
05039 
05040 >   void ChangeBrushOpParam::SwapBOOL(BOOL& First, BOOL& Second)
05041     
05042     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05043     Created:    18/11/99
05044     Inputs:     First - the first value
05045                 Second - the value to swap with
05046     Outputs:    -
05047     Returns:    -
05048     Purpose:    Swaps the two BOOL values
05049     Errors:     -
05050 
05051 ********************************************************************************************/
05052 
05053 void ChangeBrushOpParam::SwapBOOL(BOOL& First, BOOL& Second)
05054 {
05055     BOOL Temp = First;
05056     First = Second;
05057     Second = Temp;
05058 }
05059 
05060 /********************************************************************************************
05061 
05062 >   void ChangeBrushOpParam::SetValues(BrushData Data)
05063 
05064     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05065     Created:    18/11/99
05066     Inputs:     Data - a data object containing the values to set
05067     Outputs:    -
05068     Returns:    -
05069     Purpose:    sets the values of this opparam to those contained in the data object
05070     Errors:     -
05071 
05072 ********************************************************************************************/
05073 
05074 void ChangeBrushOpParam::SetValues(BrushData Data)
05075 {
05076     m_NewSpacing            = Data.m_BrushSpacing;
05077     m_NewSpacingIncrConst   = Data.m_BrushSpacingIncrConst;
05078     m_NewSpacingIncrProp    = Data.m_BrushSpacingIncrProp;
05079     m_NewSpacingMaxRand     = Data.m_BrushSpacingMaxRand;
05080     m_NewSpacingRandSeed    = Data.m_BrushSpacingRandSeed;
05081     m_NewScaling            = Data.m_BrushScaling;
05082     m_NewScalingIncr        = Data.m_BrushScalingIncr;
05083     m_NewScalingIncrConst   = Data.m_BrushScalingIncrConst;
05084     m_NewScalingMaxRand     = Data.m_BrushScalingMaxRand;
05085     m_NewScalingRandSeed    = Data.m_BrushScalingRandSeed;
05086     m_NewScalingMaxPressure = Data.m_ScalingMaxPressure;
05087     m_NewPathOffsetType     = Data.m_PathOffsetType;
05088     m_NewOffsetTypeRandSeed = Data.m_OffsetTypeRandSeed;
05089     m_NewPathOffsetVal      = Data.m_PathOffsetValue;
05090     m_NewOffsetIncrConst    = Data.m_PathOffsetIncrConst;
05091     m_NewOffsetIncrProp     = Data.m_PathOffsetIncrProp;
05092     m_NewOffsetValMaxRand   = Data.m_OffsetValueMaxRand;
05093     m_NewOffsetValRandSeed  = Data.m_OffsetValueRandSeed;
05094     m_bNewTiled             = Data.m_bTile;
05095     m_bNewRotated           = Data.m_bRotate;
05096     m_NewRotateAngle        = Data.m_RotateAngle;
05097     m_NewRotationIncrProp   = Data.m_RotAngleIncrProp;
05098     m_NewRotationIncrConst  = Data.m_RotAngleIncrConst;
05099     m_NewRotateMaxRand      = Data.m_RotationMaxRand;
05100     m_NewRotateRandSeed     = Data.m_RotationRandSeed;
05101     m_NewRotationMaxPressure = Data.m_RotationMaxPressure;
05102     m_bNewUseLocalFillColour = Data.m_bUseLocalFillColour;
05103     m_bNewUseNamed           = Data.m_bUseNamedColour;
05104     m_NewSequenceType        = Data.m_SequenceType;
05105     m_NewSequenceRandSeed    = Data.m_SequenceRandSeed;
05106     m_NewHueMaxRand          = Data.m_BrushHueMaxRand;
05107     m_NewHueRandSeed         = Data.m_BrushHueRandSeed;
05108     m_NewSatMaxRand          = Data.m_BrushSatMaxRand;
05109     m_NewSatRandSeed         = Data.m_BrushSatRandSeed;
05110     m_NewTransp              = Data.m_BrushTransparency;
05111     m_NewTranspPressure      = Data.m_TranspMaxPressure;
05112 
05113 }
05114 
05115 //------------------------------------------------------------------------------------------------
05116 //------------------------------------------------------------------------------------------------
05117 //------------------------------------------------------------------------------------------------
05118 // The RemoveTimeStampPointsAction class
05119 
05120 /********************************************************************************************
05121 
05122 >   RemoveTimeStampPointsAction::RemoveTimeStampPointsAction()
05123 
05124     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05125     Created:    18/11/99
05126     Inputs:     -
05127     Outputs:    -
05128     Returns:    -
05129     Purpose:    Constructor for the action
05130     Errors:     -
05131     SeeAlso:    -
05132 
05133 ********************************************************************************************/
05134 
05135 RemoveTimeStampPointsAction::RemoveTimeStampPointsAction()
05136 {
05137     m_pTimeStampList = NULL;
05138 }
05139 
05140 
05141 /********************************************************************************************
05142 
05143 >   RemoveTimeStampPointsAction::~RemoveTimeStampPointsAction()
05144 
05145     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05146     Created:    18/11/99
05147     Inputs:     -
05148     Outputs:    -
05149     Returns:    -
05150     Purpose:    destructor for the action
05151     Errors:     -
05152     SeeAlso:    -
05153 
05154 ********************************************************************************************/
05155 
05156 
05157 RemoveTimeStampPointsAction::~RemoveTimeStampPointsAction()
05158 {
05159     if (m_pTimeStampList != NULL)
05160         delete m_pTimeStampList;
05161 }
05162 
05163 /********************************************************************************************
05164 
05165 >   ActionCode RemoveTimeStampPointsAction::Init(   Operation*      pOp,
05166                                             ActionList*     pActionList,
05167                                             AttrBrushType * pAttrBrush,
05168                                             MILLIPOINT      StartDistance,
05169                                             MILLIPOINT      EndDistamce,
05170                                             RemoveTimeStampPointsAction** ppNewAction);
05171 
05172     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05173     Created:    18/11/99
05174     Inputs:     pOp             = ptr to the operation to which this action belongs
05175                 pActionList     =  ptr to action list to which this action should be added
05176                 pAttrBrush      - the brush attribute to perform the action on
05177                 StartDistance   - the distance to start removing at
05178                 EndDistance     - the distance to stop removing at
05179     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
05180                                   a pointer to the created action
05181     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05182     Purpose:    This is the function which creates an instance of this action. If there is no room 
05183                 in the undo buffer (which is determined by the base class Init function called within)
05184                 the function will either return AC_NO_RECORD which means the operation can continue, 
05185                 but no undo information needs to be stored, or AC_OK which means the operation should
05186                 continue AND record undo information. If the function returns AC_FAIL, there was not 
05187                 enough memory to record the undo information, and the user has decided not to continue
05188                 with the operation.
05189 
05190                 This function actually changes the blend node in a way specified in pChangeParam
05191     Errors:     -
05192     SeeAlso:    Action::Init()
05193 
05194 ********************************************************************************************/
05195 
05196 ActionCode RemoveTimeStampPointsAction::Init(Operation* pOp, ActionList* pActionList, 
05197                                             AttrBrushType* pAttrBrush, MILLIPOINT StartDistance,
05198                                             MILLIPOINT EndDistance, TimeStampList* pTimeStampList,
05199                                             RemoveTimeStampPointsAction** ppNewAction)
05200 {
05201     ERROR2IF(pAttrBrush == NULL,AC_FAIL,"pAttrBrush is NULL");
05202     ERROR2IF(StartDistance < 0, AC_FAIL, "Invalid start distance");
05203 
05204     // just check that we do actually have a time stamping brush attribute, if not then just quit
05205     if (!pAttrBrush->IsTimeStamping())
05206         return AC_OK;
05207     // Get the attribute value, just to make sure
05208     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
05209     if (pVal == NULL)
05210         return AC_FAIL;
05211 
05212     // make the new action
05213     UINT32 ActSize = sizeof(RemoveTimeStampPointsAction);
05214     RemoveTimeStampPointsAction* pNewAction;
05215     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(RemoveTimeStampPointsAction),(Action**)&pNewAction);
05216     *ppNewAction = pNewAction;
05217 
05218     if (Ac != AC_FAIL)
05219     {
05220         
05221         // if the list is NULL then we are removing points
05222         if (pTimeStampList == NULL)
05223         {
05224             //allocate a new list to store the deleted points in
05225             pTimeStampList = new TimeStampList;
05226             if (pTimeStampList == NULL)
05227             {
05228                 delete pNewAction;
05229                 return AC_FAIL;
05230             }
05231 
05232             pVal->DeleteTimeStampPoints(StartDistance, EndDistance, pTimeStampList);
05233         //  m_pAttrBrush = pAttrBrush;
05234         //  m_StartDistance = StartDistance;
05235         //  m_EndDistance = EndDistance;
05236         }
05237         // otherwise we are undoing
05238         else
05239         {
05240             pVal->AddTimeStampPoints(pTimeStampList, StartDistance);
05241             delete pTimeStampList;
05242             pTimeStampList = NULL;
05243         }
05244         pNewAction->m_pTimeStampList = pTimeStampList;
05245         pNewAction->m_pAttrBrush = pAttrBrush;
05246         pNewAction->m_StartDistance = StartDistance;
05247         pNewAction->m_EndDistance = EndDistance;
05248 
05249         // tell the attr we are changing the list, so don't reposition
05250         pVal->SetTimeStampUpdateType(UPDATE_LISTANDPOSITION);
05251     }
05252     return Ac;
05253 }
05254 
05255 
05256 
05257 /********************************************************************************************
05258 
05259 >   ActionCode RemoveTimeStampPointsAction::Execute();
05260 
05261     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05262     Created:    18/11/99
05263     Inputs:     -
05264     Outputs:    -
05265     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05266     Purpose:    Executes the action.  This will reset the num blend steps in pThisNodeBrush to OldNumSteps,
05267                 after creating another action to record the current num steps of pThisNodeBrush
05268     Errors:     -
05269     SeeAlso:    Action::Init()
05270 
05271 ********************************************************************************************/
05272 
05273 ActionCode RemoveTimeStampPointsAction::Execute()
05274 {
05275     
05276     ActionCode Act;
05277     RemoveTimeStampPointsAction* pAction;
05278     Act = RemoveTimeStampPointsAction::Init(pOperation,pOppositeActLst,m_pAttrBrush,m_StartDistance, m_EndDistance, m_pTimeStampList, &pAction);
05279     // this gets deleted in the Init, but not nulled
05280     m_pTimeStampList = NULL;
05281     return Act;
05282 }
05283 
05284 
05285 //------------------------------------------------------------------------------------------------
05286 //------------------------------------------------------------------------------------------------
05287 //------------------------------------------------------------------------------------------------
05288 // The AddTimeStampPointsAction class
05289 
05290 /********************************************************************************************
05291 
05292 >   AddTimeStampPointsAction::AddTimeStampPointsAction()
05293 
05294     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05295     Created:    18/11/99
05296     Inputs:     -
05297     Outputs:    -
05298     Returns:    -
05299     Purpose:    Constructor for the action
05300     Errors:     -
05301     SeeAlso:    -
05302 
05303 ********************************************************************************************/
05304 
05305 AddTimeStampPointsAction::AddTimeStampPointsAction()
05306 {
05307     m_pTimeStampList = NULL;
05308 }
05309 
05310 
05311 /********************************************************************************************
05312 
05313 >   AddTimeStampPointsAction::~AddTimeStampPointsAction()
05314 
05315     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05316     Created:    18/11/99
05317     Inputs:     -
05318     Outputs:    -
05319     Returns:    -
05320     Purpose:    destructor for the action
05321     Errors:     -
05322     SeeAlso:    -
05323 
05324 ********************************************************************************************/
05325 
05326 
05327 AddTimeStampPointsAction::~AddTimeStampPointsAction()
05328 {
05329     if (m_pTimeStampList != NULL)
05330         delete m_pTimeStampList;
05331 }
05332 
05333 /********************************************************************************************
05334 
05335 >   ActionCode AddTimeStampPointsAction::Init(  Operation*      pOp,
05336                                             ActionList*     pActionList,
05337                                             AttrBrushType * pAttrBrush,
05338                                             TimeStampList* pNewPoints,
05339                                             MILLIPOINT      StartDistamce,
05340                                             AddTimeStampPointsAction** ppNewAction);
05341 
05342     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05343     Created:    18/11/99
05344     Inputs:     pOp             = ptr to the operation to which this action belongs
05345                 pActionList     =  ptr to action list to which this action should be added
05346                 pAttrBrush      - the brush attribute to perform the action on
05347                 pNewPoints      - the points to add to the list
05348                 StartDistance   - the distance to start adding the points 
05349     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
05350                                   a pointer to the created action
05351     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05352     Purpose:    This is the function which creates an instance of this action. If there is no room 
05353                 in the undo buffer (which is determined by the base class Init function called within)
05354                 the function will either return AC_NO_RECORD which means the operation can continue, 
05355                 but no undo information needs to be stored, or AC_OK which means the operation should
05356                 continue AND record undo information. If the function returns AC_FAIL, there was not 
05357                 enough memory to record the undo information, and the user has decided not to continue
05358                 with the operation.
05359 
05360                 This function actually changes the blend node in a way specified in pChangeParam
05361     Errors:     -
05362     SeeAlso:    Action::Init()
05363 
05364 ********************************************************************************************/
05365 
05366 ActionCode AddTimeStampPointsAction::Init(Operation* pOp, ActionList* pActionList, 
05367                                             AttrBrushType* pAttrBrush, TimeStampList* pNewPoints,
05368                                             MILLIPOINT StartDistance, MILLIPOINT EndDistance, 
05369                                             size_t NumPoints, AddTimeStampPointsAction** ppNewAction)
05370 {
05371     ERROR2IF(pAttrBrush == NULL,AC_FAIL,"pAttrBrush is NULL");
05372     ERROR2IF(StartDistance < 0, AC_FAIL, "Invalid start distance");
05373 
05374     // just check that we do actually have a time stamping brush attribute, if not then just quit
05375     if (!pAttrBrush->IsTimeStamping())
05376         return AC_OK;
05377     // Get the attribute value, just to make sure
05378     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
05379     if (pVal == NULL)
05380         return AC_FAIL;
05381 
05382     // make the new action
05383     UINT32 ActSize = sizeof(AddTimeStampPointsAction);
05384     AddTimeStampPointsAction* pNewAction;
05385     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(AddTimeStampPointsAction),(Action**)&pNewAction);
05386     *ppNewAction = pNewAction;
05387 
05388     if (Ac != AC_FAIL)
05389     {
05390         // if the list is NULL then we are removing points
05391         if (pNewPoints == NULL)
05392         {
05393             //allocate a new list to store the deleted points in
05394             pNewPoints = new TimeStampList;
05395             if (pNewPoints == NULL)
05396             {
05397                 delete pNewAction;
05398                 return AC_FAIL;
05399             }
05400 
05401             pVal->DeleteTimeStampPoints(StartDistance, EndDistance, pNewPoints);
05402         }
05403         // otherwise we are adding
05404         else
05405         {   
05406             pVal->AddTimeStampPoints(pNewPoints, StartDistance);
05407             NumPoints = (UINT32)pNewPoints->size();
05408         /*  // we want to find out the distance between the start and end points, 
05409             // as the list may well have been sorted by the time we come to undo
05410             TimeStampBrushPoint StartPoint  = pNewPoints->GetHead();
05411             TimeStampBrushPoint EndPoint = pNewPoints->GetTail();
05412             MILLIPOINT ListDistance = EndPoint.m_Distance - StartPoint.m_Distance;
05413             pNewAction->m_EndDistance = StartDistance + ListDistance ;*/
05414             
05415             delete pNewPoints;
05416             pNewPoints = NULL;
05417         }
05418         pNewAction->m_pAttrBrush = pAttrBrush;
05419         pNewAction->m_pTimeStampList = pNewPoints;
05420         pNewAction->m_StartDistance = StartDistance;
05421         pNewAction->m_EndDistance = EndDistance;
05422         pNewAction->m_NumPoints = NumPoints;
05423         
05424         // tell the attr we are changing the list, so don't reposition
05425         pVal->SetTimeStampUpdateType(UPDATE_LISTANDPOSITION);
05426         
05427         TRACEUSER( "Diccon", _T("Start = %d, End = %d\n"), StartDistance, pNewAction->m_EndDistance);
05428 
05429         
05430     }
05431     return Ac;
05432 }
05433 
05434 
05435 
05436 /********************************************************************************************
05437 
05438 >   ActionCode AddTimeStampPointsAction::Execute();
05439 
05440     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05441     Created:    18/11/99
05442     Inputs:     -
05443     Outputs:    -
05444     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05445     Purpose:    Executes the action.  This will reset the num blend steps in pThisNodeBrush to OldNumSteps,
05446                 after creating another action to record the current num steps of pThisNodeBrush
05447     Errors:     -
05448     SeeAlso:    Action::Init()
05449 
05450 ********************************************************************************************/
05451 
05452 ActionCode AddTimeStampPointsAction::Execute()
05453 {
05454     ActionCode Act;
05455     AddTimeStampPointsAction* pAction;
05456     size_t NumPoints;
05457     if (m_pTimeStampList != NULL)
05458         NumPoints = m_pTimeStampList->size();
05459     else
05460         NumPoints = m_NumPoints;
05461     Act = AddTimeStampPointsAction::Init( pOperation, pOppositeActLst, m_pAttrBrush, m_pTimeStampList, 
05462         m_StartDistance, m_EndDistance, NumPoints, &pAction );
05463 
05464     // the list gets deleted in the Init but not NULLED
05465     m_pTimeStampList = NULL;
05466 
05467     return Act;
05468 }
05469 
05470 
05471 //------------------------------------------------------------------------------------------------
05472 //------------------------------------------------------------------------------------------------
05473 //------------------------------------------------------------------------------------------------
05474 // The UpdateBrushAction class
05475 
05476 /********************************************************************************************
05477 
05478 >   UpdateBrushAction::UpdateBrushAction()
05479 
05480     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05481     Created:    18/11/99
05482     Inputs:     -
05483     Outputs:    -
05484     Returns:    -
05485     Purpose:    Constructor for the action
05486     Errors:     -
05487     SeeAlso:    -
05488 
05489 ********************************************************************************************/
05490 
05491 UpdateBrushAction::UpdateBrushAction()
05492 {
05493     m_pNodePath = NULL;
05494 }
05495 
05496 
05497 /********************************************************************************************
05498 
05499 >   UpdateBrushAction::~UpdateBrushAction()
05500 
05501     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05502     Created:    18/11/99
05503     Inputs:     -
05504     Outputs:    -
05505     Returns:    -
05506     Purpose:    destructor for the action
05507     Errors:     -
05508     SeeAlso:    -
05509 
05510 ********************************************************************************************/
05511 
05512 
05513 UpdateBrushAction::~UpdateBrushAction()
05514 {
05515 
05516 }
05517 
05518 /********************************************************************************************
05519 
05520 >   ActionCode UpdateBrushAction::Init(     Operation*      pOp,
05521                                             ActionList*     pActionList,
05522                                             AttrBrushType * pAttrBrush,
05523                                             BrushList* pNewPoints,
05524                                             MILLIPOINT      StartDistamce,
05525                                             UpdateBrushAction** ppNewAction);
05526 
05527     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05528     Created:    18/11/99
05529     Inputs:     pOp             = ptr to the operation to which this action belongs
05530                 pActionList     =  ptr to action list to which this action should be added
05531                 pNewPoints      - the points to add to the list
05532                 StartDistance   - the distance to start adding the points 
05533     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
05534                                   a pointer to the created action
05535     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05536     Purpose:    This is the function which creates an instance of this action. If there is no room 
05537                 in the undo buffer (which is determined by the base class Init function called within)
05538                 the function will either return AC_NO_RECORD which means the operation can continue, 
05539                 but no undo information needs to be stored, or AC_OK which means the operation should
05540                 continue AND record undo information. If the function returns AC_FAIL, there was not 
05541                 enough memory to record the undo information, and the user has decided not to continue
05542                 with the operation.
05543 
05544                 This function actually changes the blend node in a way specified in pChangeParam
05545     Errors:     -
05546     SeeAlso:    Action::Init()
05547 
05548 ********************************************************************************************/
05549 
05550 ActionCode UpdateBrushAction::Init(Operation* pOp, ActionList* pActionList,  NodePath* pNodePath, 
05551                                    UpdateBrushAction** ppNewAction)
05552 {
05553     ERROR2IF(pNodePath == NULL, AC_FAIL, "Nodepath is NULL");
05554 
05555     // Change here now that our attributes are being factored again - we can't rely on pAttrBrush
05556     // not having been deleted so get a new one each time
05557 
05558     AttrBrushType* pBrush = NULL;
05559     pNodePath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), (NodeAttribute**)&pBrush);
05560     if (pBrush == NULL)
05561         return AC_OK;
05562 
05563     // just check that our brush isn't a default
05564     if (pBrush->GetBrushHandle() == BrushHandle_NoBrush)
05565         return AC_OK;
05566     // Get the attribute value, just to make sure
05567     BrushAttrValue* pVal = (BrushAttrValue*)pBrush->GetAttributeValue();
05568     if (pVal == NULL)
05569         return AC_FAIL;
05570 
05571     // make the new action
05572     UINT32 ActSize = sizeof(UpdateBrushAction);
05573     UpdateBrushAction* pNewAction;
05574     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(UpdateBrushAction),(Action**)&pNewAction);
05575     *ppNewAction = pNewAction;
05576 
05577     // all we really do is ask the brush to update itself
05578     if (Ac != AC_FAIL)
05579         pBrush->NodePathUpdated(&(pNodePath->InkPath));
05580 
05581     pNewAction->m_pNodePath = pNodePath;
05582 
05583     return Ac;
05584 }
05585 
05586 
05587 
05588 /********************************************************************************************
05589 
05590 >   ActionCode UpdateBrushAction::Execute();
05591 
05592     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05593     Created:    18/11/99
05594     Inputs:     -
05595     Outputs:    -
05596     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05597     Purpose:    Executes the action.  This will reset the num blend steps in pThisNodeBrush to OldNumSteps,
05598                 after creating another action to record the current num steps of pThisNodeBrush
05599     Errors:     -
05600     SeeAlso:    Action::Init()
05601 
05602 ********************************************************************************************/
05603 
05604 ActionCode UpdateBrushAction::Execute()
05605 {
05606     ActionCode Act;
05607     UpdateBrushAction* pAction;
05608     Act = UpdateBrushAction::Init(pOperation,pOppositeActLst, m_pNodePath, &pAction);
05609 
05610     return Act;
05611 }
05612 
05613 
05614 
05615 //------------------------------------------------------------------------------------------------
05616 //------------------------------------------------------------------------------------------------
05617 //------------------------------------------------------------------------------------------------
05618 // The SetTimeStampUpdateTypeAction class
05619 
05620 /********************************************************************************************
05621 
05622 >   SetTimeStampUpdateTypeAction::SetTimeStampUpdateTypeAction()
05623 
05624     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05625     Created:    18/11/99
05626     Inputs:     -
05627     Outputs:    -
05628     Returns:    -
05629     Purpose:    Constructor for the action
05630     Errors:     -
05631     SeeAlso:    -
05632 
05633 ********************************************************************************************/
05634 
05635 SetTimeStampUpdateTypeAction::SetTimeStampUpdateTypeAction()
05636 {
05637     m_pNodePath = NULL;
05638     m_pAttrBrush = NULL;
05639     m_TypeToSet = UPDATE_NONE;
05640 }
05641 
05642 
05643 /********************************************************************************************
05644 
05645 >   SetTimeStampUpdateTypeAction::~SetTimeStampUpdateTypeAction()
05646 
05647     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05648     Created:    18/11/99
05649     Inputs:     -
05650     Outputs:    -
05651     Returns:    -
05652     Purpose:    destructor for the action
05653     Errors:     -
05654     SeeAlso:    -
05655 
05656 ********************************************************************************************/
05657 
05658 
05659 SetTimeStampUpdateTypeAction::~SetTimeStampUpdateTypeAction()
05660 {
05661 
05662 }
05663 
05664 /********************************************************************************************
05665 
05666 >   ActionCode SetTimeStampUpdateTypeAction::Init(  Operation*      pOp,
05667                                             ActionList*     pActionList,
05668                                             AttrBrushType * pAttrBrush,
05669                                             BrushList* pNewPoints,
05670                                             MILLIPOINT      StartDistamce,
05671                                             SetTimeStampUpdateTypeAction** ppNewAction);
05672 
05673     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05674     Created:    18/11/99
05675     Inputs:     pOp             = ptr to the operation to which this action belongs
05676                 pActionList     =  ptr to action list to which this action should be added
05677                 pAttrBrush      - the brush attribute to perform the action on
05678                 pNewPoints      - the points to add to the list
05679                 StartDistance   - the distance to start adding the points 
05680     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
05681                                   a pointer to the created action
05682     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05683     Purpose:    This is the function which creates an instance of this action. If there is no room 
05684                 in the undo buffer (which is determined by the base class Init function called within)
05685                 the function will either return AC_NO_RECORD which means the operation can continue, 
05686                 but no undo information needs to be stored, or AC_OK which means the operation should
05687                 continue AND record undo information. If the function returns AC_FAIL, there was not 
05688                 enough memory to record the undo information, and the user has decided not to continue
05689                 with the operation.
05690 
05691                 This function actually changes the blend node in a way specified in pChangeParam
05692     Errors:     -
05693     SeeAlso:    Action::Init()
05694 
05695 ********************************************************************************************/
05696 
05697 ActionCode SetTimeStampUpdateTypeAction::Init(Operation* pOp, ActionList* pActionList, AttrBrushType* pAttrBrush,
05698                                        NodePath* pNodePath,ListUpdateType TypeToSet, SetTimeStampUpdateTypeAction** ppNewAction)
05699 {
05700     ERROR2IF(pAttrBrush == NULL,AC_FAIL,"pAttrBrush is NULL");
05701     ERROR2IF(pNodePath == NULL, AC_FAIL, "Nodepath is NULL");
05702 
05703     // just check that our brush isn't a default
05704     if (pAttrBrush->GetBrushHandle() == BrushHandle_NoBrush)
05705         return AC_OK;
05706     // Get the attribute value, just to make sure
05707     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
05708     if (pVal == NULL)
05709         return AC_FAIL;
05710 
05711     // make the new action
05712     UINT32 ActSize = sizeof(SetTimeStampUpdateTypeAction);
05713     SetTimeStampUpdateTypeAction* pNewAction;
05714     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(SetTimeStampUpdateTypeAction),(Action**)&pNewAction);
05715     *ppNewAction = pNewAction;
05716 
05717     // all we really do is ask the brush to update itself
05718     if (Ac != AC_FAIL)
05719         pVal->SetTimeStampUpdateType(TypeToSet);
05720 
05721     // set the members of the undo action
05722     pNewAction->m_pAttrBrush = pAttrBrush;
05723     pNewAction->m_pNodePath = pNodePath;
05724     pNewAction->m_TypeToSet= TypeToSet;
05725 
05726     return Ac;
05727 }
05728 
05729 
05730 
05731 /********************************************************************************************
05732 
05733 >   ActionCode SetTimeStampUpdateTypeAction::Execute();
05734 
05735     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05736     Created:    18/11/99
05737     Inputs:     -
05738     Outputs:    -
05739     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05740     Purpose:    Executes the action.  This will reset the num blend steps in pThisNodeBrush to OldNumSteps,
05741                 after creating another action to record the current num steps of pThisNodeBrush
05742     Errors:     -
05743     SeeAlso:    Action::Init()
05744 
05745 ********************************************************************************************/
05746 
05747 ActionCode SetTimeStampUpdateTypeAction::Execute()
05748 {
05749     ActionCode Act;
05750     SetTimeStampUpdateTypeAction* pAction;
05751     Act = SetTimeStampUpdateTypeAction::Init(pOperation,pOppositeActLst,m_pAttrBrush, m_pNodePath, m_TypeToSet, &pAction);
05752 
05753     return Act;
05754 }
05755 
05756 
05757 //------------------------------------------------------------------------------------------------
05758 //------------------------------------------------------------------------------------------------
05759 //------------------------------------------------------------------------------------------------
05760 // The RemovePressurePointsAction class
05761 
05762 /********************************************************************************************
05763 
05764 >   RemovePressurePointsAction::RemovePressurePointsAction()
05765 
05766     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05767     Created:    18/11/99
05768     Inputs:     -
05769     Outputs:    -
05770     Returns:    -
05771     Purpose:    Constructor for the action
05772     Errors:     -
05773     SeeAlso:    -
05774 
05775 ********************************************************************************************/
05776 
05777 RemovePressurePointsAction::RemovePressurePointsAction()
05778 {
05779     m_pPressureSampler = NULL;
05780 }
05781 
05782 
05783 /********************************************************************************************
05784 
05785 >   RemovePressurePointsAction::~RemovePressurePointsAction()
05786 
05787     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05788     Created:    18/11/99
05789     Inputs:     -
05790     Outputs:    -
05791     Returns:    -
05792     Purpose:    destructor for the action
05793     Errors:     -
05794     SeeAlso:    -
05795 
05796 ********************************************************************************************/
05797 
05798 
05799 RemovePressurePointsAction::~RemovePressurePointsAction()
05800 {
05801     if (m_pPressureSampler != NULL)
05802         delete m_pPressureSampler;
05803 }
05804 
05805 /********************************************************************************************
05806 
05807 >   ActionCode RemovePressurePointsAction::Init(    Operation*      pOp,
05808                                             ActionList*     pActionList,
05809                                             AttrBrushType * pAttrBrush,
05810                                             MILLIPOINT      StartDistance,
05811                                             MILLIPOINT      EndDistamce,
05812                                             RemovePressurePointsAction** ppNewAction);
05813 
05814     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05815     Created:    18/11/99
05816     Inputs:     pOp             = ptr to the operation to which this action belongs
05817                 pActionList     =  ptr to action list to which this action should be added
05818                 pAttrBrush      - the brush attribute to perform the action on
05819                 StartIndex      - the index in the pressure list to begin removing at
05820                 NumPoints       - the number of points to remove
05821     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
05822                                   a pointer to the created action
05823     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05824     Purpose:    This is the function which creates an instance of this action. If there is no room 
05825                 in the undo buffer (which is determined by the base class Init function called within)
05826                 the function will either return AC_NO_RECORD which means the operation can continue, 
05827                 but no undo information needs to be stored, or AC_OK which means the operation should
05828                 continue AND record undo information. If the function returns AC_FAIL, there was not 
05829                 enough memory to record the undo information, and the user has decided not to continue
05830                 with the operation.
05831 
05832 
05833     Errors:     -
05834     SeeAlso:    Action::Init()
05835 
05836 ********************************************************************************************/
05837 
05838 ActionCode RemovePressurePointsAction::Init(Operation* pOp, ActionList* pActionList, 
05839                                             AttrBrushType* pAttrBrush, UINT32 StartIndex,
05840                                             UINT32 NumPoints, CSampleData* pPressureData,
05841                                             RemovePressurePointsAction** ppNewAction)
05842 {
05843     ERROR2IF(pAttrBrush == NULL,AC_FAIL,"pAttrBrush is NULL");
05844     
05845     // just check that we do actually have a time stamping brush attribute, if not then just quit
05846     if (!pAttrBrush->ContainsPressureCache())
05847         return AC_OK;
05848     // Get the attribute value, just to make sure
05849     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
05850     if (pVal == NULL)
05851         return AC_FAIL;
05852     
05853     // make the new action
05854     UINT32 ActSize = sizeof(RemovePressurePointsAction);
05855     RemovePressurePointsAction* pNewAction;
05856     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(RemovePressurePointsAction),(Action**)&pNewAction);
05857     *ppNewAction = pNewAction;
05858 
05859     if (Ac != AC_FAIL)
05860     {
05861         
05862         // if the list is NULL then we are removing points
05863         if (pPressureData == NULL)
05864         {
05865             //allocate a new list to store the deleted points in
05866             pPressureData = new CSampleData;
05867             if (pPressureData == NULL)
05868             {
05869                 delete pNewAction;
05870                 return AC_FAIL;
05871             }
05872             // initialise the array 
05873             if (!pPressureData->InitialiseData(NumPoints))
05874             {
05875                 delete pNewAction;
05876                 delete pPressureData;
05877                 return AC_FAIL;
05878             }
05879 
05880                 pVal->DeletePressurePoints(StartIndex, NumPoints, pPressureData->GetSampleArray());
05881                 pPressureData->SetNumItemsFromArraySize();
05882         //  m_pAttrBrush = pAttrBrush;
05883         //  m_StartDistance = StartDistance;
05884         //  m_EndDistance = EndDistance;
05885         }
05886         // otherwise we are undoing
05887         else
05888         {
05889             pVal->AddPressurePoints(pPressureData, StartIndex);
05890             delete pPressureData;
05891             pPressureData = NULL;
05892         }
05893         pNewAction->m_pPressureSampler = pPressureData;
05894         pNewAction->m_pAttrBrush = pAttrBrush;
05895         pNewAction->m_StartIndex = StartIndex;
05896         pNewAction->m_NumPoints  = NumPoints;
05897 
05898         pAttrBrush->ClearCachedRect();
05899 
05900         // tell the attr we are changing the list, so don't reposition
05901         pVal->SetPressureUpdateType(UPDATE_LISTANDPOSITION);
05902     }
05903     return Ac;
05904 }
05905 
05906 
05907 
05908 /********************************************************************************************
05909 
05910 >   ActionCode RemovePressurePointsAction::Execute();
05911 
05912     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05913     Created:    18/11/99
05914     Inputs:     -
05915     Outputs:    -
05916     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
05917     Purpose:    Executes the action.  This will reset the num blend steps in pThisNodeBrush to OldNumSteps,
05918                 after creating another action to record the current num steps of pThisNodeBrush
05919     Errors:     -
05920     SeeAlso:    Action::Init()
05921 
05922 ********************************************************************************************/
05923 
05924 ActionCode RemovePressurePointsAction::Execute()
05925 {
05926     TRACEUSER( "Diccon", _T("\nUNDOING REMOVE PRESSURE POINTS\n"));
05927     ActionCode Act;
05928     RemovePressurePointsAction* pAction;
05929     Act = RemovePressurePointsAction::Init(pOperation,pOppositeActLst,m_pAttrBrush,m_StartIndex, m_NumPoints,  m_pPressureSampler, &pAction);
05930     // this gets deleted in the Init, but not nulled
05931     m_pPressureSampler = NULL;
05932     return Act;
05933 }
05934 
05935 
05936 
05937 //------------------------------------------------------------------------------------------------
05938 //------------------------------------------------------------------------------------------------
05939 //------------------------------------------------------------------------------------------------
05940 // The AddPressurePointsAction class
05941 
05942 /********************************************************************************************
05943 
05944 >   AddPressurePointsAction::AddPressurePointsAction()
05945 
05946     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05947     Created:    18/11/99
05948     Inputs:     -
05949     Outputs:    -
05950     Returns:    -
05951     Purpose:    Constructor for the action
05952     Errors:     -
05953     SeeAlso:    -
05954 
05955 ********************************************************************************************/
05956 
05957 AddPressurePointsAction::AddPressurePointsAction()
05958 {
05959     m_pPressureSampler = NULL;
05960 }
05961 
05962 
05963 /********************************************************************************************
05964 
05965 >   AddPressurePointsAction::~AddPressurePointsAction()
05966 
05967     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05968     Created:    18/11/99
05969     Inputs:     -
05970     Outputs:    -
05971     Returns:    -
05972     Purpose:    destructor for the action
05973     Errors:     -
05974     SeeAlso:    -
05975 
05976 ********************************************************************************************/
05977 
05978 
05979 AddPressurePointsAction::~AddPressurePointsAction()
05980 {
05981     if (m_pPressureSampler != NULL)
05982         delete m_pPressureSampler;
05983 }
05984 
05985 /********************************************************************************************
05986 
05987 >   ActionCode AddPressurePointsAction::Init(   Operation*      pOp,
05988                                             ActionList*     pActionList,
05989                                             AttrBrushType * pAttrBrush,
05990                                             PressureList* pNewPoints,
05991                                             MILLIPOINT      StartDistamce,
05992                                             AddPressurePointsAction** ppNewAction);
05993 
05994     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05995     Created:    18/11/99
05996     Inputs:     pOp             = ptr to the operation to which this action belongs
05997                 pActionList     =  ptr to action list to which this action should be added
05998                 pAttrBrush      - the brush attribute to perform the action on
05999                 pNewPoints      - the points to add to the list
06000                 StartDistance   - the distance to start adding the points 
06001     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
06002                                   a pointer to the created action
06003     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
06004     Purpose:    This is the function which creates an instance of this action. If there is no room 
06005                 in the undo buffer (which is determined by the base class Init function called within)
06006                 the function will either return AC_NO_RECORD which means the operation can continue, 
06007                 but no undo information needs to be stored, or AC_OK which means the operation should
06008                 continue AND record undo information. If the function returns AC_FAIL, there was not 
06009                 enough memory to record the undo information, and the user has decided not to continue
06010                 with the operation.
06011 
06012                 This function actually changes the blend node in a way specified in pChangeParam
06013     Errors:     -
06014     SeeAlso:    Action::Init()
06015 
06016 ********************************************************************************************/
06017 
06018 ActionCode AddPressurePointsAction::Init(Operation* pOp, ActionList* pActionList, 
06019                                             AttrBrushType* pAttrBrush, CSampleData* pNewPoints,
06020                                             UINT32 StartIndex, size_t NumPoints, 
06021                                             AddPressurePointsAction** ppNewAction)
06022 {
06023     ERROR2IF(pAttrBrush == NULL,AC_FAIL,"pAttrBrush is NULL");
06024 
06025     // just check that we do actually have a pressure brush attribute, if not then just quit
06026     if (!pAttrBrush->ContainsPressureCache())
06027         return AC_OK;
06028     // Get the attribute value, just to make sure
06029     BrushAttrValue* pVal = (BrushAttrValue*)pAttrBrush->GetAttributeValue();
06030     if (pVal == NULL)
06031         return AC_FAIL;
06032 
06033     // make the new action
06034     UINT32 ActSize = sizeof(AddPressurePointsAction);
06035     AddPressurePointsAction* pNewAction;
06036     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(AddPressurePointsAction),(Action**)&pNewAction);
06037     *ppNewAction = pNewAction;
06038 
06039     if (Ac != AC_FAIL)
06040     {
06041         // if the CSampleData is NULL then we are removing points
06042         if (pNewPoints == NULL)
06043         {
06044             //allocate a new list to store the deleted points in
06045             pNewPoints = new CSampleData;
06046             if (pNewPoints == NULL)
06047             {
06048                 delete pNewAction;
06049                 return AC_FAIL;
06050             }
06051             // initialise the array
06052             if (!pNewPoints->InitialiseData(NumPoints))
06053             {
06054                 delete pNewAction;
06055                 delete pNewPoints;
06056                 return AC_FAIL;
06057             }
06058 
06059             pVal->DeletePressurePoints(StartIndex, NumPoints, pNewPoints->GetSampleArray());
06060             // we must calculate num items ourselves
06061             pNewPoints->SetNumItemsFromArraySize();
06062         }
06063         // otherwise we are adding
06064         else
06065         {   
06066             pNewPoints->ClipArray(NumPoints);
06067             pVal->AddPressurePoints(pNewPoints, StartIndex);
06068             NumPoints = (UINT32)pNewPoints->GetNumItems();
06069             
06070             delete pNewPoints;
06071             pNewPoints = NULL;
06072         }
06073         pNewAction->m_pAttrBrush = pAttrBrush;
06074         pNewAction->m_pPressureSampler = pNewPoints;
06075         pNewAction->m_StartIndex = StartIndex;
06076         pNewAction->m_NumPoints = NumPoints;
06077         
06078         pAttrBrush->ClearCachedRect();
06079 
06080         // tell the attr we are changing the list, so don't reposition
06081         pVal->SetPressureUpdateType(UPDATE_LISTANDPOSITION);
06082         
06083     //  TRACEUSER( "Diccon", _T("Start = %d, End = %d\n"), StartDistance, pNewAction->m_EndDistance);
06084 
06085         
06086     }
06087     return Ac;
06088     
06089 }
06090 
06091 
06092 
06093 /********************************************************************************************
06094 
06095 >   ActionCode AddPressurePointsAction::Execute();
06096 
06097     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
06098     Created:    18/11/99
06099     Inputs:     -
06100     Outputs:    -
06101     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
06102     Purpose:    Executes the action.  This will reset the num blend steps in pThisNodeBrush to OldNumSteps,
06103                 after creating another action to record the current num steps of pThisNodeBrush
06104     Errors:     -
06105     SeeAlso:    Action::Init()
06106 
06107 ********************************************************************************************/
06108 
06109 ActionCode AddPressurePointsAction::Execute()
06110 {
06111     TRACEUSER( "Diccon", _T("\nUNDOING ADD PRESSURE POINTS\n"));
06112     ActionCode Act;
06113     AddPressurePointsAction* pAction;
06114     size_t NumPoints;
06115 //  if (m_pPressureSampler != NULL)
06116 //      NumPoints = m_pPressureSampler->GetNumItems();
06117 //  else
06118         NumPoints = m_NumPoints;
06119     Act = AddPressurePointsAction::Init(pOperation,pOppositeActLst,m_pAttrBrush, m_pPressureSampler, m_StartIndex, NumPoints, &pAction);
06120 
06121     // the list gets deleted in the Init but not NULLED
06122     m_pPressureSampler = NULL;
06123 
06124     return Act;
06125 }

Generated on Sat Nov 10 03:47:46 2007 for Camelot by  doxygen 1.4.4