OpDrawBrush Class Reference

Draws a freehand stroke, smooths it and applies a nice brush effect. More...

#include <opdrbrsh.h>

Inheritance diagram for OpDrawBrush:

OpFreeHand SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 OpDrawBrush ()
 Constructor.
 OpDrawBrush (FreeHandTool *pTool)
 Constructor. This simply sets a few of the operation flags.
 ~OpDrawBrush ()
 destructor.
void DoDrag (DocCoord Anchor, Spread *, INT32, BrushHandle Handle, FreeHandJoinInfo *pJoinInfo, Path *ToolPath, GRenderBrush *pGRndRgn, ClickModifiers ClickMods)
 Starts up the drag operation by storing all start positions and setting up a Path to store the mouse movement in.
virtual void DragPointerMove (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 Handles the event of the mouse moving during a drag.
virtual void DragPointerIdle (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 Handles the mouse idle events.
virtual void DragFinished (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL Success, BOOL bSolidDrag)
 Handles the drag finishing by rubbing out an EOR on the screen and adding the path to the tree and building all the undo that will be needed.
void RenderDragBlobs (DocRect, Spread *, BOOL bSolidDrag)
 EORs the whole path onto the screen a segment at a time. It needs to do it a segment at a time as that is how it is drawn as the path is created. This has to redraw it identically or there will be bits of EORed stuff left all over the place.
virtual BOOL IsBrushOp ()
BOOL SetTimeStamp (double TimeStamp)
 to set the timestamp member

Static Public Member Functions

static BOOL Declare ()
 Adds the operation to the list of all known operations.
static OpState GetState (String_256 *Description, OpDescriptor *)
 Find out the state of the operation at the specific time.
static CDistanceSamplerGeneratePressureData (AttrBrushType *pAttrBrush, MILLIPOINT StartDistance, MILLIPOINT EndDistance, MILLIPOINT NewPathLength)
 This function deals with the case when we wish to edit a brush with pressure data but we do not generate a pressure list during the edit for some reason. In this case we must create a new pressure list and fill it with values based upon the values in the existing brush pressure list.
static MILLIPOINT GetCurrentLineWidthIfNotDefault ()
 In order to determine whether we have to tell the brush to scale to a new line width or not.

Protected Member Functions

void ResetMembers ()
 Initialises all our member variables to something sensible.
void AddPointsToPath (DocCoord Pos, Spread *pSpread)
 Adds a new point to the path of mouse moves. When the drag finishes the mouse moves will be smoothed.
virtual void SetCursorAndStatus (CursorType CurType)
 Overridden version for the brush, basically we do not offer any of the keyboard options so we wish to keep the status line blank during brush operations.
virtual BOOL ApplyAttributes (NodePath *NewPath, Document *pDocument)
 Applies the current attributes to the Node passed in. It has to find the current document to do this and will ENSURE if it fails to find one. This overridden version also finds the newly applied brush attribute and gives it the cache of points that we have been recording.
void RenderStepsForTime (double TimeSlice, Spread *pSpread)
 Renders as many steps in the brush as possible in the time available. The reason for having the code here rather than in the processor is twofold: 1) I feel the property of rendering for a certain timeslice is a property of the Op rather than the PPB; 2) In order to make use of the caching ProcessPathDistance, which belongs to the Op rather than the PPB.
BOOL InitialisePathProcessorBrush (BrushHandle Handle, MILLIPOINT Distance=0)
 To create a new pathprocessorbrush and copy all the data from the brush definitino found using BrushIndex.
BOOL InitialiseProcessPathDistance ()
 To create a new path processor object.
BOOL InitialisePressureCache ()
 To allocate the pressure array, if we need it.
AttrBrushTypeCreateNewAttribute ()
 Adds the operation to the list of all known operations.
virtual BOOL EditBrushLists (NodePath *pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
 When we are editing a brush that contains either timestamping or pressure data and we are editing using a brush we will have generated our own list of TS or pressure info that we need to insert into the existing list. This fn. manages the insertion of these lists and any others that might arise.
BOOL EditTimeStampList (NodePath *pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
 When a path is edited that has a timestamping brush applied to it we those points are stored in a list that is generated when the path is drawn. If we subsequently want to edit that path we have to insert or remove points from that list. This function works out what points should be inserted or removed, and performs that action on the applied brush. This is made slightly easier.
BOOL EditPressureList (NodePath *pNewPath, INT32 FirstChangedIndex, INT32 NumElements)
virtual BOOL SimpleJoinBrush (NodePath *pNewNodePath, Path *pNewPath)
 Joins a Simple path with the new freehand path and builds all the undo that is needed in the process.
virtual BOOL ReverseBrushPressure ()
 Calls the attribute function to reverse our pressure list.
BOOL InitialiseTimeStampList ()
 to create a new timestamp object list and assign it to our member
void RenderTimeStamp ()
 To be used in timestamp mode, obviously. This fn. determines whether or not enough time has elapsed for us to render a point. If so we render a point and cache it, updating the necessary members.
BOOL InitialisePressureSampler ()
 to create a new CSampleData object and assign it to our pointer for sampling pressure
BOOL ApplyRetroSmoother (NodePath *pNodePath, double SmoothAmount)
 Initialises the RetroSmoother object and uses it to smooth the nodepath we have created. The reason for using this smoother rather than the FreeHand smoother is that it does not seem to change the shape of the path in a visible way. It is useful to apply this because otherwise the paths that we draw have too many control points which can obscure the brush objects.
BOOL RetroSmoothBrush (NodePath *pNewNodePath)
 As above, the base class version does nothing.

Protected Attributes

MILLIPOINT m_BrushSpacing
MILLIPOINT m_LastSpacing
MILLIPOINT m_DistanceSinceLastObject
MILLIPOINT m_LastDistanceRendered
DocCoord m_LastPoint
DocCoord m_StartPoint
DocCoord m_LastPointRendered
INT32 m_NumBrushObjects
UINT32 m_NumInkObjects
UINT32 m_LastInkObjectRendered
double m_BrushScaling
GRenderBrushm_pGRenderBrush
PathProcessorBrushm_pPathProcBrush
BrushDefinitionm_pBrushDefinition
BOOL mustClearStatusBar
ApplicationpApp
ProcessPathDistancem_pProcPathDistance
FreeHandToolm_pTool
BOOL m_bFirstPointRendered
MILLIPOINT m_FirstSpacing
INT32 m_LastPathIndexRendered
PointsMapm_pPointsCache
double m_TimeStamp
double m_LastTimeStamp
TimeStampListm_pTimeStampList
MonotonicTime m_Timer
PressureListm_pPressureList
CDistanceSamplerm_pPressureSampler
UINT32 m_NumPressureVals

Private Member Functions

 CC_DECLARE_DYNCREATE (OpDrawBrush)

Detailed Description

Draws a freehand stroke, smooths it and applies a nice brush effect.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/10/99

Definition at line 139 of file opdrbrsh.h.


Constructor & Destructor Documentation

OpDrawBrush::OpDrawBrush  ) 
 

Constructor.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99

Definition at line 183 of file opdrbrsh.cpp.

00184 {
00185     ResetMembers();
00186 }

OpDrawBrush::OpDrawBrush FreeHandTool pTool  ) 
 

Constructor. This simply sets a few of the operation flags.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99

Definition at line 198 of file opdrbrsh.cpp.

00199 {
00200     ResetMembers();
00201     if (pTool != NULL)
00202         m_pTool = pTool;
00203 }

OpDrawBrush::~OpDrawBrush  ) 
 

destructor.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99

Definition at line 216 of file opdrbrsh.cpp.

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 }


Member Function Documentation

void OpDrawBrush::AddPointsToPath DocCoord  PointerPos,
Spread pSpread
[protected]
 

Adds a new point to the path of mouse moves. When the drag finishes the mouse moves will be smoothed.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/10/99
Parameters:
Pos - The position of the mouse [INPUTS] pSpread - Pointer to the spread that we are drawing on

Reimplemented from OpFreeHand.

Definition at line 1932 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::ApplyAttributes NodePath pNewPath,
Document pDocument
[protected, virtual]
 

Applies the current attributes to the Node passed in. It has to find the current document to do this and will ENSURE if it fails to find one. This overridden version also finds the newly applied brush attribute and gives it the cache of points that we have been recording.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/1/2000
Parameters:
NewPath - The NodePath to apply the current attributes to [INPUTS] pDocument - the document this path will be placed into.
Returns:
TRUE if it worked, FALSE if it did not
This fn. has changed slightly as we now have to comply with the "most recently applied attributes" option. In order to do this both the line width and the brush attribute have to be applied via the attribute manager.

Andy Hills, 18-09-00 Note - I have temporarily reverted this function to the 24-08-00 version. This fixes the problem where, if the above-mentioned option is disabled, an access violation occurs.

Reimplemented from OpFreeHand.

Definition at line 1084 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::ApplyRetroSmoother NodePath pNodePath,
double  SmoothAmount
[protected]
 

Initialises the RetroSmoother object and uses it to smooth the nodepath we have created. The reason for using this smoother rather than the FreeHand smoother is that it does not seem to change the shape of the path in a visible way. It is useful to apply this because otherwise the paths that we draw have too many control points which can obscure the brush objects.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/1/2000
Parameters:
NewPath - The NodePath that we have created [INPUTS] SmoothAmount - the amount that we wish to smooth (0 -100)
Returns:
TRUE if it worked, FALSE if it did not

Definition at line 1201 of file opdrbrsh.cpp.

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 }

OpDrawBrush::CC_DECLARE_DYNCREATE OpDrawBrush   )  [private]
 

AttrBrushType * OpDrawBrush::CreateNewAttribute  )  [protected]
 

Adds the operation to the list of all known operations.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99
Returns:
TRUE if all went OK, False otherwise

Definition at line 1247 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::Declare  )  [static]
 

Adds the operation to the list of all known operations.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99
Returns:
TRUE if all went OK, False otherwise

Reimplemented from OpFreeHand.

Definition at line 1882 of file opdrbrsh.cpp.

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 }

void OpDrawBrush::DoDrag DocCoord  Anchor,
Spread pSpread,
INT32  Smooth,
BrushHandle  Handle,
FreeHandJoinInfo pFreeHandInfo,
Path ToolPath,
GRenderBrush pGRndRgn,
ClickModifiers  ClickMods
 

Starts up the drag operation by storing all start positions and setting up a Path to store the mouse movement in.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99
Parameters:
Anchor - The position of the mouse at the start of the Drag [INPUTS] pSpread - The spread that the drag started on Smooth - Closeness of fit value Handle - the handle of the brush we want to use pFreeHandInfo - Pointer to the info about the Joining set up by the freehand tool ToolPath - The path to store the mouse tracking info in pGRndBMP - pointer to the big bitmap used to store the view

Definition at line 329 of file opdrbrsh.cpp.

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 }

void OpDrawBrush::DragFinished DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  Success,
BOOL  bSolidDrag
[virtual]
 

Handles the drag finishing by rubbing out an EOR on the screen and adding the path to the tree and building all the undo that will be needed.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/10/99
Parameters:
PointerPos - The position of the mouse at the end of the drag [INPUTS] ClickMods - the key modifiers being pressed pSpread - The spread that the drag finished on Success - TRUE if the drag was terminated properly, FALSE if it was ended with the escape key being pressed
See also:
ClickModifiers

Reimplemented from OpFreeHand.

Definition at line 966 of file opdrbrsh.cpp.

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 }

void OpDrawBrush::DragPointerIdle DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Handles the mouse idle events.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/10/99
Parameters:
PointerPos - The current position of the mouse in Doc Coords [INPUTS] ClickMods - Which key modifiers are being pressed pSpread - The spread that the mouse is moving over
See also:
ClickModifiers

Reimplemented from OpFreeHand.

Definition at line 678 of file opdrbrsh.cpp.

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 }

void OpDrawBrush::DragPointerMove DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Handles the event of the mouse moving during a drag.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/10/99
Parameters:
PointerPos - The current position of the mouse in Doc Coords [INPUTS] ClickMods - Which key modifiers are being pressed pSpread - The spread that the mouse is moving over
See also:
ClickModifiers

Reimplemented from OpFreeHand.

Definition at line 572 of file opdrbrsh.cpp.

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<