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;
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 }   

BOOL OpDrawBrush::EditBrushLists NodePath pNewPath,
INT32  FirstChangedIndex,
INT32  NumElements
[protected, virtual]
 

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.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/3/2000
Parameters:
pNewPath - The New curve that has just been draw [INPUTS] FirstChangedIndex - The first coord in the path that is to be replaced NumElements - The number of elements in the path that need replacing
Returns:
TRUE if it worked, FALSE if not

Reimplemented from OpFreeHand.

Definition at line 1321 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::EditPressureList NodePath pNewPath,
INT32  FirstChangedIndex,
INT32  NumElements
[protected]
 

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/3/2000
Parameters:
pNewPath - The New curve that has just been draw [INPUTS] FirstChangedIndex - The first coord in the path that is to be replaced NumElements - The number of elements in the path that need replacing
Returns:
TRUE if it worked, FALSE if not

Definition at line 1455 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::EditTimeStampList NodePath pNewPath,
INT32  FirstChangedIndex,
INT32  NumElements
[protected]
 

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.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/3/2000
Parameters:
pNewPath - The New curve that has just been draw [INPUTS] FirstChangedIndex - The first coord in the path that is to be replaced NumElements - The number of elements in the path that need replacing
Returns:
TRUE if it worked, FALSE if not

Definition at line 1356 of file opdrbrsh.cpp.

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 }

CDistanceSampler * OpDrawBrush::GeneratePressureData AttrBrushType pAttrBrush,
MILLIPOINT  Start,
MILLIPOINT  End,
MILLIPOINT  NewPathLength
[static]
 

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.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/3/2000
Parameters:
pAttrBrush - the brush that we are joining to [INPUTS] Start - the distance along the original path where we want to start the insert, set this to -1 to indicate we are inserting at the beginning of the path
End - the distance along the original path where we wish to end the insert, set this to -1 to indicate that we are inserting at the end of the path

NewPathLength - the length of the path that we wish to insert

Returns:
a newly generated pressure sampler, complete with values (or NULL if we fail)

Definition at line 1777 of file opdrbrsh.cpp.

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 }

MILLIPOINT OpDrawBrush::GetCurrentLineWidthIfNotDefault  )  [static]
 

In order to determine whether we have to tell the brush to scale to a new line width or not.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/5/2000
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The current line width, UNLESS the current line width is the Default attribute, in which case it returns -1

Definition at line 2329 of file opdrbrsh.cpp.

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 }

OpState OpDrawBrush::GetState String_256 Description,
OpDescriptor
[static]
 

Find out the state of the operation at the specific time.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/10/99
Parameters:
Description - GetState fills this string with an approriate description [OUTPUTS] of the current state of the push tool
Returns:
The state of the operation, so that menu items (ticks and greying can be done properly

Reimplemented from OpFreeHand.

Definition at line 1910 of file opdrbrsh.cpp.

01911 {
01912     OpState Blobby;
01913     
01914     return Blobby;
01915 }

BOOL OpDrawBrush::InitialisePathProcessorBrush BrushHandle  Handle,
MILLIPOINT  Distance = 0
[protected]
 

To create a new pathprocessorbrush and copy all the data from the brush definitino found using BrushIndex.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/11/99
Parameters:
BrushIndex - index into the array of brush definitions stored in the brush component [INPUTS] Distance - the distance along the path that we are starting at Retruns: TRUE if successful, FALSE otherwise
See also:
-

Definition at line 2095 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::InitialisePressureCache  )  [protected]
 

To allocate the pressure array, if we need it.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/11/99
Parameters:
- [INPUTS]
See also:
-

Definition at line 2202 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::InitialisePressureSampler  )  [protected]
 

to create a new CSampleData object and assign it to our pointer for sampling pressure

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/11/99
Parameters:
- [INPUTS]
Returns:
TRUE if successful, FALSE if our allocation failed.
See also:
-

Definition at line 2287 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::InitialiseProcessPathDistance  )  [protected]
 

To create a new path processor object.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/11/99
Parameters:
- [INPUTS]
See also:
-

Definition at line 2063 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::InitialiseTimeStampList  )  [protected]
 

to create a new timestamp object list and assign it to our member

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/11/99
Parameters:
- [INPUTS]
See also:
-

Definition at line 2235 of file opdrbrsh.cpp.

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 }

virtual BOOL OpDrawBrush::IsBrushOp  )  [inline, virtual]
 

Reimplemented from OpFreeHand.

Definition at line 174 of file opdrbrsh.h.

00174 { return TRUE;}

void OpDrawBrush::RenderDragBlobs DocRect  ,
Spread ,
BOOL  bSolidDrag
[inline, virtual]
 

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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/9/93
Parameters:
Rect - The Rectangle that needs to be re-rendered [INPUTS] pSpread - The spread on which the rendering is to take place
See also:
OpFreeHand::RenderLineSegment()

Reimplemented from OpFreeHand.

Definition at line 168 of file opdrbrsh.h.

00168 {}

void OpDrawBrush::RenderStepsForTime double  TimeSlice,
Spread pSpread
[protected]
 

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.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/99
Parameters:
TimeSlice - the length of time to render for [INPUTS] pSpread - the spread to render on to
Returns:
-

Definition at line 739 of file opdrbrsh.cpp.

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 }

void OpDrawBrush::RenderTimeStamp  )  [protected]
 

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.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/99
Parameters:
- [INPUTS]
Returns:
-

Definition at line 892 of file opdrbrsh.cpp.

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 }

void OpDrawBrush::ResetMembers  )  [protected]
 

Initialises all our member variables to something sensible.

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

Definition at line 248 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::RetroSmoothBrush NodePath pNewNodePath  )  [protected, virtual]
 

As above, the base class version does nothing.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/3/2000
Parameters:
pNewPath - The New curve that has just been drawn [INPUTS]
Returns:
TRUE

Reimplemented from OpFreeHand.

Definition at line 1726 of file opdrbrsh.cpp.

01727 {
01728     return ApplyRetroSmoother(pNewNodePath, 85);
01729 }

BOOL OpDrawBrush::ReverseBrushPressure  )  [protected, virtual]
 

Calls the attribute function to reverse our pressure list.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/3/2000
Parameters:
[INPUTS] 
Returns:
TRUE if it worked, FALSE if it failed, or if we aren't using pressure

Reimplemented from OpFreeHand.

Definition at line 1744 of file opdrbrsh.cpp.

01745 {
01746     if (m_pPressureSampler == NULL)
01747         return FALSE;
01748 
01749     return m_pPressureSampler->ReverseData();
01750 }

void OpDrawBrush::SetCursorAndStatus CursorType  CurType  )  [protected, virtual]
 

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.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
4/7/2000
Parameters:
CurType - The type of cursor to change to [INPUTS]

Reimplemented from OpFreeHand.

Definition at line 1986 of file opdrbrsh.cpp.

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 }

BOOL OpDrawBrush::SetTimeStamp double  TimeStamp  ) 
 

to set the timestamp member

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/11/99
Parameters:
Value of timestamp to use in ms. [INPUTS]
Returns:
TRUE unless Timestamp is outside the specified bounds
See also:
-

Definition at line 2264 of file opdrbrsh.cpp.

02265 {
02266     if (TimeStamp < MIN_TIMESTAMP || TimeStamp > MAX_TIMESTAMP)
02267         return FALSE;
02268 
02269     m_TimeStamp = TimeStamp;
02270     return TRUE;
02271 }

BOOL OpDrawBrush::SimpleJoinBrush NodePath pInsertedNode,
Path pNewPath
[protected, virtual]
 

Joins a Simple path with the new freehand path and builds all the undo that is needed in the process.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/3/2000
Parameters:
pInsertedNode - the node that we have just inserted [INPUTS] pPath - the new section of path that we have just drawn
Returns:
TRUE if it worked, FALSE if it failed
This version also incorporates code to insert timestamping or pressure data if we are editing such a brush

Reimplemented from OpFreeHand.

Definition at line 1605 of file opdrbrsh.cpp.

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 }


Member Data Documentation

BOOL OpDrawBrush::m_bFirstPointRendered [protected]
 

Definition at line 257 of file opdrbrsh.h.

double OpDrawBrush::m_BrushScaling [protected]
 

Definition at line 242 of file opdrbrsh.h.

MILLIPOINT OpDrawBrush::m_BrushSpacing [protected]
 

Definition at line 230 of file opdrbrsh.h.

MILLIPOINT OpDrawBrush::m_DistanceSinceLastObject [protected]
 

Definition at line 232 of file opdrbrsh.h.

MILLIPOINT OpDrawBrush::m_FirstSpacing [protected]
 

Definition at line 259 of file opdrbrsh.h.

MILLIPOINT OpDrawBrush::m_LastDistanceRendered [protected]
 

Definition at line 233 of file opdrbrsh.h.

UINT32 OpDrawBrush::m_LastInkObjectRendered [protected]
 

Definition at line 240 of file opdrbrsh.h.

INT32 OpDrawBrush::m_LastPathIndexRendered [protected]
 

Definition at line 261 of file opdrbrsh.h.

DocCoord OpDrawBrush::m_LastPoint [protected]
 

Definition at line 234 of file opdrbrsh.h.

DocCoord OpDrawBrush::m_LastPointRendered [protected]
 

Definition at line 236 of file opdrbrsh.h.

MILLIPOINT OpDrawBrush::m_LastSpacing [protected]
 

Definition at line 231 of file opdrbrsh.h.

double OpDrawBrush::m_LastTimeStamp [protected]
 

Definition at line 270 of file opdrbrsh.h.

INT32 OpDrawBrush::m_NumBrushObjects [protected]
 

Definition at line 237 of file opdrbrsh.h.

UINT32 OpDrawBrush::m_NumInkObjects [protected]
 

Definition at line 239 of file opdrbrsh.h.

UINT32 OpDrawBrush::m_NumPressureVals [protected]
 

Definition at line 282 of file opdrbrsh.h.

BrushDefinition* OpDrawBrush::m_pBrushDefinition [protected]
 

Definition at line 248 of file opdrbrsh.h.

GRenderBrush* OpDrawBrush::m_pGRenderBrush [protected]
 

Definition at line 244 of file opdrbrsh.h.

PathProcessorBrush* OpDrawBrush::m_pPathProcBrush [protected]
 

Definition at line 245 of file opdrbrsh.h.

PointsMap* OpDrawBrush::m_pPointsCache [protected]
 

Definition at line 264 of file opdrbrsh.h.

PressureList* OpDrawBrush::m_pPressureList [protected]
 

Definition at line 277 of file opdrbrsh.h.

CDistanceSampler* OpDrawBrush::m_pPressureSampler [protected]
 

Definition at line 280 of file opdrbrsh.h.

ProcessPathDistance* OpDrawBrush::m_pProcPathDistance [protected]
 

Definition at line 254 of file opdrbrsh.h.

TimeStampList* OpDrawBrush::m_pTimeStampList [protected]
 

Definition at line 271 of file opdrbrsh.h.

FreeHandTool* OpDrawBrush::m_pTool [protected]
 

Definition at line 255 of file opdrbrsh.h.

DocCoord OpDrawBrush::m_StartPoint [protected]
 

Definition at line 235 of file opdrbrsh.h.

MonotonicTime OpDrawBrush::m_Timer [protected]
 

Definition at line 272 of file opdrbrsh.h.

double OpDrawBrush::m_TimeStamp [protected]
 

Definition at line 269 of file opdrbrsh.h.

BOOL OpDrawBrush::mustClearStatusBar [protected]
 

Definition at line 250 of file opdrbrsh.h.

Application* OpDrawBrush::pApp [protected]
 

Definition at line 251 of file opdrbrsh.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:58:03 2007 for Camelot by  doxygen 1.4.4