FreeHandTool Class Reference

This class handles the Free Hand Tool that is used to draw lines that follow the path of the Mouse Pointer. More...

#include <freehand.h>

Inheritance diagram for FreeHandTool:

DragTool Tool_v1 List of all members.

Public Member Functions

 FreeHandTool ()
 Dummp Constructor - It does nothing. All the real initialisation is done in FreeHandTool::Init which is called by the Tool Manager.
 ~FreeHandTool ()
 Destructor (Virtual). Does nothing.
BOOL Init ()
 Used to check if the Tool was properly constructed.
void Describe (void *InfoPtr)
 Allows the tool manager to extract information about the tool.
UINT32 GetID ()
virtual void SelectChange (BOOL)
 Called when the tool is selected or deselected. Creates and pushes the tool's cursor; pops and destroys it.
virtual void OnClick (DocCoord, ClickType, ClickModifiers, Spread *)
 To handle a Mouse Click event for the FreeHand Tool. It starts up a FreeHand Operation.
virtual void OnMouseMove (DocCoord, Spread *, ClickModifiers)
 This routine is called whenever the mouse moves while we're in the freehand tool. it sees what is under the pointer, and flips the cursor if clicking will have a different effect. The rules are:.
virtual BOOL GetStatusLineText (String_256 *ptext, Spread *, DocCoord, ClickModifiers)
 Sets the status line text on request from the app.
virtual BOOL OnIdle ()
virtual void RenderToolBlobs (Spread *, DocRect *)
 Renders the Tools Blobs. This will be used to draw paths as they are retro fitted live, as the accuracy bar is dragged!
void SetSmoothness (INT32 Smooth)
 Sets the freehand tools accuracy setting.
INT32 GetSmoothness ()
 for finding out the freehand tools current smoothing accuracy value
void PreviousPathInvalid ()
 Marks the previous path as invalid. After calling this function, attempts to re-fit a path by changing the smoothing values will be ignored. This function should be called when something happens that would make it impossible to re-fit the path (eg the original is translated or rotated or undone).
void SetPreviousPath (NodePath *, INT32 Start, INT32 Len)
 Marks the previously drawn path as valid so that it can be retro fitted. Retro fitting will be allowed until PreviousPathInvalid() is called.
FreeHandInfoBarOpGetInfoBar ()
BOOL IsRetroPathStillValid ()
 Finds out if we are able to do retro fitting and is used by the info bar as well as the tool when it becomes the selected tool and when a drag of the slider starts.
INT32 BuildPathCRC (NodePath *)
 Goes though the path and adds all the coordinate offsets together to come up with a number that will hopefully identify the path uniquly, so that we can tell if this is in fact the path we want, only translated.
void TranslateTrackData ()
 If the path in the tree has been translated since it was drawn, we have to translate the original retro fit data to match. This functions checks if a translation is required, and translates all the coords if it is needed.
void RetroFitChanging ()
 Tries to re-fit the previous path with the current smoothness setting.
void RetroFitFinished ()
 Should be called when any changes to the accuracy slider have been completed.
void CreateBrush ()
 Called from the infobar, creates a brush definition from the ink objects in the selection and passes it over to the BrushComponent. Also creates a GRenderBrush render region which is used for rendering the brush into when the user begins to draw.
void SetCurrentBrushHandle ()
 Sets the brush handle member to that of the current default brush attribute.
MILLIPOINT GetBrushSpacing ()
 for finding out the freehand tools current brush spacing
void SetBrushSpacing (MILLIPOINT Spacing)
 for setting the freehand tools current brush spacing
BrushHandle GetBrushHandle ()
void BrushFinished ()
 Called by OpDrawBrush to tell the tool that the previous draw brush op has finished. Therefore the tool must prepare for the next one (if any).
BOOL BrushSelected (BrushHandle Handle, BOOL ApplyToSelection=TRUE)
 sets the brushhandle member of the tool to Handle. Designed to be called by the infobar when it receives a brushmessage. Also initiates a number of steps that must be taken to ensure that real time drawing with this brush can proceed smoothly
BOOL ApplyBrushToSelection (BrushHandle Handle)
 Applies the chosen brush to all items in the selection via the attribute manager. However we do not want to make this a default attribute so if the selection is empty then nothing happens.
void ScreenChanged (BOOL WipeRegion=FALSE)
 Called by the infobar to let the tool know that the screen has changed. Essentially this means that if we are in brush drawing mode then we need to blit the contents of the screen into our big render region.
void InitialiseJoinInfoForBrush (AttrBrushType *pAttrBrush, NodePath *pNodePath, DocCoord JoinPoint)
 Initialises the JoinInfo struct so that we correctly join the existing brush.
void BrushDeleted (BrushHandle Handle)
 Lets the tool know that a brush has been deactivated (we call it deleted in the UI but its actually still there). If this brush is the current brush then we need to set the current brush to default. Also informs the infobar.
BOOL SetBrushUpdateState (UPDATE_STATE State)
 Tells us when we should next update the offscreen buffer used by the brush. Often it is wise ot wait until the next idle to update because that gives time for the screen to redraw after the brush combo has closed.

Static Public Attributes

static BOOL FreehandPtrCrosshair = FALSE
 Determine whether freehand pointer has crosshairs or not.

Protected Member Functions

GRenderBrushGetBigGRenderBrush (Spread *pSpread)
 Gets a GRenderBrush the size of the current view, then renders into it the contents of the current view.
BOOL InitialiseBrushBitmaps (GRenderBrush *pGRender)
 To work out how large our brush bitmaps must be and allocate them to the render region supplied.
BrushDefinitionGetSelectedBrush ()
 In order to determine which brush to draw with when performing a real time draw brush operation.
BOOL LoadCursors ()
 Loads all the cursors used by the freehand tool and pushs the normal one onto the top of the cursor stack.
void RemoveCursors ()
 Pops the freehand tools cursor off the top of the cursor stack, frees the memory used by all the cursors in the freehand tool and sets all the pointers to NULL.
void ChangeCursor (Cursor *pCursor)
 Changes to the specified cursor. Will only change the cursor if it isn't already this cursor, so it doesn't flicker.
BOOL IsCursorNearEndPoint (NodePath *pPath, const DocRect &BlobRect)
 Scans the path in the NodePath to see any of its endpoints lie inside the DocRect supplied. The DocRect should be the snapping rectangle around the cursor position. If this function finds that one of the endpoints is in the rect, it will remember the path, and the position of the endpoint so that when a new freehand line is started, this data can be passed in. This function also changes the cursor to the Join cursor and sets the status bar text if it finds a match.
BOOL IsCursorNearPath (NodePath *pPath, INT32 Range, const DocCoord &PointerPos)
 This function tests to see if any point along the paths length is close to the cursor. If it finds that it is, then the cursor and the status bar help are changed and the information about the path is remembered in case a drag starts soon.
BOOL GetNewPaths ()
 Gets rid of the old path data and creates new paths. One of the useful side effects of doing this is that it helps to keep the path data near the top of the heap, make the freehand tool seem more responsive.
BOOL DeletePaths ()
 Deletes the paths that hold the track data and the smoothed path and sets thier params to NULL.
BOOL InitialiseBlendRef (NodeRenderableInk *pInk)
 To initialise a BlendRef object.
BOOL NodeHasLineWidth (NodeRenderableInk *pNode)
void SetColourEditorProcessing (BOOL Value)
 Tells the colour editor whether or not to do timer processing, we need to turn it off in order to draw a brush stroke.
DocRect GetLargestInkBoundingRect ()
 as above, note that the m_brushinknodes pointer must be initialised
void InitialiseBrushInkNodeArray (UINT32 NumObjects)
 Clears out the m_BrushRefPtrArray if it is not empty, and sets the size.
void LaunchBrushDefinitionDialog (BrushHandle Handle)
 launches the brush edit dialog for the brush handle supplied. A good idea to call this just after creating a brush so the user can edit it before using it.

Protected Attributes

GRenderBrushm_pGRenderBrush
UPDATE_STATE m_UpdateBrushState
INT32 Smoothness
String_256 StatusMsg
DocCoord StartPos
SpreadStartSpread
PathTrackData
PathRetroPath
INT32 StartSlot
INT32 NumSlots
INT32 PathCRC
NodePathPreviousPath
BOOL AreWeRetroFitting
BOOL IsPreviousPathValid
BOOL IsRetroPathValid
BOOL IsSelectBlobsOnScreen
CursorpNormalCursor
CursorpJoinCursor
CursorpActiveCursor
CursorpModifyCursor
INT32 CurrentCursorID
FreeHandJoinInfo JoinInfo
FreeHandInfoBarOppInfoBarOp
std::vector< NodeRenderableInk * > m_BrushInkNodeArray
BlendRefm_pBlendRef
MILLIPOINT m_BrushSpacing
UINT32 m_NumInkNodes
BrushHandle m_BrushHandle
BOOL m_bBrushReady
String_256 m_LastBrushDocument

Static Protected Attributes

static TCHARFamilyName = _T("Drawing Tools")
static TCHARToolName = _T("Free Hand Tool")
static TCHARPurpose = _T("To Draw arbitrary lines")
static TCHARAuthor = _T("Rik")

Private Member Functions

 CC_DECLARE_MEMDUMP (FreeHandTool)

Detailed Description

This class handles the Free Hand Tool that is used to draw lines that follow the path of the Mouse Pointer.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/93

Definition at line 170 of file freehand.h.


Constructor & Destructor Documentation

FreeHandTool::FreeHandTool  ) 
 

Dummp Constructor - It does nothing. All the real initialisation is done in FreeHandTool::Init which is called by the Tool Manager.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93
See also:
FreeHandTool::Init

Definition at line 205 of file freehand.cpp.

00206 {
00207     // The Default smoothness
00208     Smoothness = 50;
00209     
00210     // No info bar or previous path by default
00211     pInfoBarOp = NULL;
00212     PreviousPath = NULL;
00213 
00214     // The previous path is not valid
00215     IsPreviousPathValid = FALSE;
00216     IsRetroPathValid = FALSE;
00217     AreWeRetroFitting = FALSE;
00218 
00219     // The actual paths
00220     TrackData = NULL;
00221     RetroPath = NULL;
00222 
00223     // Positions in the previous path to default values
00224     StartSlot = 0;
00225     NumSlots = 0;
00226     
00227     // Set the cursor pointers to null
00228     pNormalCursor = NULL;
00229     pActiveCursor = NULL;
00230     pJoinCursor = NULL;
00231 
00232     // Set the vars to deal with the Joining of paths
00233     JoinInfo.pJoinPath = NULL;
00234     JoinInfo.IsNearEndPoint = FALSE;
00235     JoinInfo.CloseSlot = 0;
00236     JoinInfo.Into = 0.0;
00237     JoinInfo.pAttrBrush = NULL;
00238     JoinInfo.FirstBrushSpacing = 25;
00239 
00240     // Make sure that the status line text is a valid string
00241     StatusMsg = String_256("");
00242     
00243     m_pBlendRef     = NULL;
00244     m_BrushSpacing  = 10000;
00245     m_NumInkNodes   = 0;
00246     m_pGRenderBrush = NULL;
00247     m_BrushHandle   = BrushHandle_NoBrush;
00248     
00249     m_LastBrushDocument = TEXT("No document");
00250 }

FreeHandTool::~FreeHandTool  ) 
 

Destructor (Virtual). Does nothing.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93

Definition at line 264 of file freehand.cpp.

00265 {
00266     //Clear out the old paths
00267     DeletePaths();
00268 PORTNOTE("other", "Removed m_pGRenderBrush support");
00269 #ifndef EXCLUDE_FROM_XARALX
00270     if (m_pGRenderBrush != NULL)
00271         delete m_pGRenderBrush;
00272 #endif
00273 }


Member Function Documentation

BOOL FreeHandTool::ApplyBrushToSelection BrushHandle  Handle  ) 
 

Applies the chosen brush to all items in the selection via the attribute manager. However we do not want to make this a default attribute so if the selection is empty then nothing happens.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/99
Parameters:
Handle to the selected brush [INPUTS]
- [OUTPUTS]
Returns:
TRUE if successful, FALSE otherwise

Definition at line 2680 of file freehand.cpp.

02681 {
02682     // first check to see if we have a selection
02683     SelRange* pSel = GetApplication()->FindSelection();
02684     if (pSel == NULL)
02685     {
02686         ERROR3("No selection in FreeHandTool::ApplyBrushToSelection");
02687         return FALSE;
02688     }
02689 
02690     // we have decided that if the selection is not empty then we will not try to 
02691     // go ahead and apply the attribute, as this gets annoying when you only want to 
02692     // draw with a different brush
02693     if (pSel->IsEmpty())
02694         return TRUE;
02695 
02696     // ok so we have a selection, now get an attribute node from the brush component
02697     NodeAttribute* pNewAttr = BrushComponent::CreateNode(Handle);
02698     if (pNewAttr != NULL)
02699         AttributeManager::AttributeSelected(pNewAttr);
02700 
02701     // we may have a scenario where we wish to apply the default brush
02702     if (Handle == BrushHandle_NoBrush)
02703     {
02704         // in this case we just need to make an attribute node
02705         NodeAttribute* pAttr = new AttrBrushType;
02706         if (pAttr != NULL)
02707             AttributeManager::AttributeSelected(pAttr);
02708     }
02709     return TRUE;
02710     
02711 }

void FreeHandTool::BrushDeleted BrushHandle  Handle  ) 
 

Lets the tool know that a brush has been deactivated (we call it deleted in the UI but its actually still there). If this brush is the current brush then we need to set the current brush to default. Also informs the infobar.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/99
Parameters:
Handle to the brush that has been deleted [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 2579 of file freehand.cpp.

02580 {
02581     if (Handle == m_BrushHandle)
02582         BrushSelected(BrushHandle_NoBrush, FALSE);
02583 
02584     if (pInfoBarOp != NULL)
02585         pInfoBarOp->RemoveBrush(Handle);
02586 }

void FreeHandTool::BrushFinished  ) 
 

Called by OpDrawBrush to tell the tool that the previous draw brush op has finished. Therefore the tool must prepare for the next one (if any).

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/99
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-
TRACEUSER( "Diccon", _T("Brush Finished\n"));

Definition at line 2601 of file freehand.cpp.

02602 {
02603     // turn the colour picker back on
02604     SetColourEditorProcessing(TRUE);
02605     
02606     // turn background rendering back on 
02607     Document* pDoc = Document::GetSelected();
02608     DocView* pDocView = pDoc->GetFirstDocView();
02609     
02610     while (pDocView)
02611     {
02612         pDocView->SetPreventRenderView(FALSE);
02613         pDocView = pDoc->GetNextDocView(pDocView);
02614     }
02615 
02616     /*
02617     DocView* pDocView = DocView::GetSelected(); //gotta be getselected in case we have multiple views
02618     if (pDocView != NULL)
02619         pDocView->SetPreventRenderView(FALSE);
02620     */
02621     m_bBrushReady = FALSE;
02622     m_UpdateBrushState = UPDATE_ONIDLE;
02624     BrushSelected(m_BrushHandle, FALSE);
02625 
02626 
02627 }

BOOL FreeHandTool::BrushSelected BrushHandle  Handle,
BOOL  ApplyToSelection = TRUE
 

sets the brushhandle member of the tool to Handle. Designed to be called by the infobar when it receives a brushmessage. Also initiates a number of steps that must be taken to ensure that real time drawing with this brush can proceed smoothly

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/99
Parameters:
Handle to the selected brush [INPUTS] ApplyToSelection - whether or not we wish to apply this brush to the selection
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if something went wrong

Definition at line 2398 of file freehand.cpp.

02399 {
02400     if (m_UpdateBrushState == UPDATE_NEVER)
02401         return TRUE;
02402 
02403     // first apply what we've got to the selection
02404     if (ApplyToSelection)
02405     {
02406         // if this fails then quit
02407         if (!ApplyBrushToSelection(Handle))
02408             return FALSE;
02409 
02410         m_UpdateBrushState = UPDATE_ONIDLE; // So that we update on the next idle rather than immediately
02411     }
02412 
02413     //TRACEUSER( "Diccon", _T("Start Brush selected\n"));
02414     m_BrushHandle = Handle;
02415     
02416     // note that we do not do the update straight unless the flag is set.  If it is not set then
02417     // we set the flag and then do the update on the next idle event.  The reason for this is that
02418     // if we do not wait then the brush combo will still be on the screen whilst we do our screen grab
02419 
02420     if (m_UpdateBrushState == UPDATE_NOW)
02421         m_UpdateBrushState = UPDATE_NEVER;
02422     else
02423     {   
02424         m_UpdateBrushState = UPDATE_ONIDLE;
02425         return TRUE;
02426     }
02427 
02428     // if its the 'null' brush then just kill the render region and leave
02429     if (m_BrushHandle == BrushHandle_NoBrush)
02430     {
02431 PORTNOTE("other", "Removed m_pGRenderBrush support");
02432 #ifndef EXCLUDE_FROM_XARALX
02433         if (m_pGRenderBrush != NULL)
02434         {
02435             delete m_pGRenderBrush;
02436             m_pGRenderBrush = NULL;
02437         }
02438 #endif
02439         return TRUE;
02440     }
02441 
02442 PORTNOTE("other", "Removed m_pGRenderBrush support");
02443 #ifndef EXCLUDE_FROM_XARALX
02444     // if we are <24BPP display then make the whole thing again from scratch
02445     // as we will need different sized brush bitmaps and everything
02446     if (m_pGRenderBrush != NULL && m_pGRenderBrush->GetScreenDepth() < 24)
02447     {
02448         delete m_pGRenderBrush;
02449         m_pGRenderBrush = NULL;
02450     }
02451 
02452     String_32 ProgString = _T("Preparing brush, please wait..");
02453     Progress Hourglass(&ProgString, -1, FALSE);
02454     
02455     // set smoothness to zero
02456 //  SetSmoothness(0);
02457 
02458     Spread* pCurrentSpread = Document::GetSelectedSpread();
02459     // make a new GRenderBrush for the new brush
02460     if (pCurrentSpread == NULL)
02461     {
02462         ERROR3("No Spread in FreeHandTool::BrushSelected");
02463         return FALSE;
02464     }
02465         
02466     // inform the join info of what we're going to draw
02467     JoinInfo.m_BrushHandle = m_BrushHandle;
02468     
02469     if (m_pGRenderBrush == NULL)
02470     {
02471         m_pGRenderBrush = GetBigGRenderBrush(pCurrentSpread);
02472     
02473         if (m_pGRenderBrush != NULL)
02474         {
02475             if (!InitialiseBrushBitmaps(m_pGRenderBrush))
02476             {
02477                 InformWarning(_R(IDS_BRUSHBITMAP_INVALID));
02478                 delete m_pGRenderBrush;
02479                 m_pGRenderBrush = NULL;
02480 
02481                 return FALSE;
02482             }
02483 
02484             m_bBrushReady = TRUE;
02485 
02486         }
02487         else
02488         {
02489             ToolInformError(_R(IDS_OUT_OF_MEMORY));
02490         
02491             return FALSE;
02492         }
02493     }
02494     else
02495     {
02496         // grab whats on the screen
02497         BOOL ok = m_pGRenderBrush->CaptureView(pCurrentSpread);
02498 
02499         // tell GDraw to use this bitmap
02500         if (ok) m_pGRenderBrush->SetupMainBitmap();
02501         return ok; //m_pGRenderBrush->CaptureView(pCurrentSpread);
02502     }
02503 #endif
02504 
02505     return TRUE;
02506 }

INT32 FreeHandTool::BuildPathCRC NodePath PrevPath  ) 
 

Goes though the path and adds all the coordinate offsets together to come up with a number that will hopefully identify the path uniquly, so that we can tell if this is in fact the path we want, only translated.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/6/94
Parameters:
PrevPath - The path to build a CRC checksum for. [INPUTS]
Returns:
The CRC checksum for the path, relative to the first coord

Definition at line 1378 of file freehand.cpp.

01379 {
01380     INT32 TotalCRC = 0;
01381 
01382     // Get at the path in the NodePath
01383     Path* CRCPath = &(PrevPath->InkPath);
01384 
01385     // Find out about the coords and how many there are
01386     DocCoord* Coords = CRCPath->GetCoordArray();
01387     INT32 NumCoords = StartSlot+NumSlots;
01388 
01389     // go though the coords
01390     for (INT32 i=StartSlot; i<NumCoords; i++)
01391     {
01392         // Get the coords relative from the first coord
01393         // making this process transparent to trnslation
01394         // Add it in to the CRC total
01395         TotalCRC += (Coords[i].x-Coords[StartSlot].x) + (Coords[i].y-Coords[StartSlot].y);
01396     }
01397 
01398     // return the CRC I have
01399     return TotalCRC;
01400 }

FreeHandTool::CC_DECLARE_MEMDUMP FreeHandTool   )  [private]
 

void FreeHandTool::ChangeCursor Cursor pCursor  )  [protected]
 

Changes to the specified cursor. Will only change the cursor if it isn't already this cursor, so it doesn't flicker.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/3/94
Parameters:
ID of the cursor you want to flip to [INPUTS]
Returns:
Errors: can fail if the cursor cannot be created - the cursor code will fail.

Definition at line 708 of file freehand.cpp.

00709 {
00710     // only change if this cursor is different from the current cursor
00711     if ((pCursor!=pActiveCursor) && (pCursor!=NULL))
00712     {
00713         // set this cursor as the current cursor and immediately display it
00714         CursorStack::GSetTop(pCursor, CurrentCursorID);
00715 
00716         // remember this is our current cursor
00717         pActiveCursor = pCursor;
00718     }
00719 }

void FreeHandTool::CreateBrush  ) 
 

Called from the infobar, creates a brush definition from the ink objects in the selection and passes it over to the BrushComponent. Also creates a GRenderBrush render region which is used for rendering the brush into when the user begins to draw.

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

Definition at line 1758 of file freehand.cpp.

01759 {
01760     //TRACEUSER( "Diccon", _T("\nCreating Brush"));
01761 
01762 
01763         SelRange* pSel = GetApplication()->FindSelection();
01764 
01765         if (pSel == NULL)
01766         {
01767             return ;
01768         }
01769 
01770         m_NumInkNodes = 0;
01771 
01772         Node* pNode = pSel->FindFirst();
01773         
01774         if (pNode == NULL)
01775         {
01776             InformWarning(_R(IDS_BRUSHCREATENOSEL));
01777             return;
01778         }
01779 
01780         // first count the number of objects
01781         while (pNode != NULL)
01782         {
01783             if (pNode->IsAnObject())
01784             {
01785                 if (BrushDefinition::ObjectCanCreateBrush((NodeRenderableInk*)pNode))
01786                     m_NumInkNodes++;
01787 
01788                 if (m_NumInkNodes >= MAX_BRUSH_OBJECTS)
01789                 {
01790                     InformWarning(_R(IDS_BRUSHCREATE_TOOMANY));
01791                     break;
01792                 }
01793             }
01794             pNode = pSel->FindNext(pNode);
01795         }
01796 
01797         if (m_NumInkNodes == 0)
01798         {
01799             InformWarning(_R(IDS_BRUSHCREATE_INVALID));
01800             return;
01801         }
01802 
01803         InitialiseBrushInkNodeArray((UINT32)m_NumInkNodes);
01804         
01805         DocRect BBox; // 
01806 
01807         // iterate through again and assign the selection pointers to the new array
01808         UINT32 Counter = 0;
01809         pNode = pSel->FindFirst();
01810 
01811         while (pNode != NULL && Counter < m_NumInkNodes)
01812         {
01813             if (pNode->IsAnObject())
01814             {               
01815                 // check to see that its not too big
01816                 BBox = ((NodeRenderableInk*)pNode)->GetBoundingRect();
01817                 if (BBox.Height() > MAX_BRUSH_SPACING || BBox.Width() > MAX_BRUSH_SPACING)
01818                 {
01819                     InformWarning(_R(IDS_BRUSH_TOOBIG));
01820                     return;
01821                 }
01822                 if (BrushDefinition::ObjectCanCreateBrush((NodeRenderableInk*)pNode))
01823                 {
01824                     m_BrushInkNodeArray[Counter++] = (NodeRenderableInk*)pNode;
01825                 }
01826             }
01827             pNode = pSel->FindNext(pNode);
01828         }
01829     
01830         Spread *pBrushSpread = new Spread;
01831         if (pBrushSpread == NULL)
01832         {
01833             ERROR3("Couldn't create new brush spread");
01834             return;
01835         }
01836 
01837         Layer *pBrushLayer = new Layer(pBrushSpread, FIRSTCHILD, String_256(TEXT("Diccon did this")));
01838         if (pBrushLayer == NULL)
01839         {
01840             ERROR3("Couldn't create new brush (5)");
01841             delete pBrushSpread;
01842             return;
01843         }
01844 
01845         BOOL LineWidth = FALSE;
01846         BOOL Compound = FALSE;
01847         // And attach the clipart tree to our new layer
01848         Node* pLastNode = NULL;
01849 //      AttrBrushType* pAttrBrush = NULL;
01850 
01851         for (UINT32 i = 0; i < m_NumInkNodes; i++)
01852         {
01853             NodeRenderableInk* pInk = m_BrushInkNodeArray[i];
01854             
01855             // do a quick line width check - we need this info later
01856             if (NodeHasLineWidth(pInk))
01857                 LineWidth = TRUE;
01858             if (pInk->IsCompound())
01859                 Compound = TRUE;
01860             pInk->MakeAttributeComplete();
01861 
01862             Node* pInsertNode = NULL;
01863             // OK if we're trying to make a brush out of an object that is already a brush then 
01864             // convert the object to normal shapes first.
01865         /*  pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), 
01866                                                     (NodeAttribute**)&pAttrBrush);
01867 
01868             if (pAttrBrush && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush)
01869             {
01870                 //Turn the brush into a group with lots of nodepaths
01871                 BrushBecomeAGroup BecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), NULL);
01872                 pAttrBrush->DoBecomeA(&BecomeA, pInk);
01873         
01874                 // the brush will create a group out of itself and we want to retrieve that
01875                 NodeGroup* pBrushGroup = BecomeA.GetNodeGroup();
01876                 if (pBrushGroup != NULL)
01877                     pInsertNode = pBrushGroup;
01878                 else
01879                 {
01880                     ERROR3("Unable to make group from brush");
01881                     return;
01882                 }
01883 
01884                 pAttrBrush = NULL;
01885             }
01886             else*/
01887             {   
01888                 // the normal case
01889                 pInsertNode = pInk->PublicCopy();
01890                 
01891                 if (pInsertNode == NULL)
01892                 {
01893                     ERROR3("Error copying node");
01894                     return;
01895                 }
01896 
01897                 pInk->CopyChildrenTo(pInsertNode);
01898             
01899             }
01900             pInk->NormaliseAttributes();
01901             if (i==0)
01902                 pInsertNode->AttachNode(pBrushLayer, FIRSTCHILD, FALSE, TRUE);
01903             else
01904                 pInsertNode->AttachNode(pLastNode, NEXT, FALSE, TRUE);
01905 
01906             pLastNode = pInsertNode;
01907         }
01908 
01909         // convert any indexed colours in our subtree
01910         LineDefinition::ConvertIndexedColours(pBrushSpread);
01911 
01912         // now create the brush definition
01913         BrushDefinition* pBrushDef = new BrushDefinition(pBrushSpread);
01914 
01915         if (pBrushDef == NULL)
01916         {
01917             ERROR3("Couldn't allocate brush def");
01918             delete pBrushSpread;
01919             delete pBrushLayer;
01920             return;
01921         }
01922 
01923         // just double check
01924         if (!pBrushDef->IsActivated())
01925         {
01926             ERROR3("Brush failed to initialise correctly, aborting Create Brush");
01927             delete pBrushDef;
01928             delete pBrushSpread;
01929             delete pBrushLayer;
01930             return;
01931         }
01932 
01933         // set the default spacing
01934         DocRect BRect = pBrushDef->GetLargestBoundingBox();
01935         MILLIPOINT Width = BRect.Width();
01936         if (pBrushDef->GetNumBrushObjects() > 1 || LineWidth || Compound)
01937         {
01938             MILLIPOINT Spacing = (MILLIPOINT)(Width * 1.1);
01939             if (Spacing > MAX_BRUSH_SPACING)
01940                 Spacing = MAX_BRUSH_SPACING;
01941 
01942             pBrushDef->SetSpacing(Spacing);
01943         }
01944         else
01945             pBrushDef->SetSpacing(Width / 5);
01946 
01947         // get the brush component of the document
01948         Document* pDoc = Document::GetCurrent();
01949         if (pDoc == NULL)
01950         {
01951             ERROR3("No document");
01952             delete pBrushSpread;
01953             delete pBrushLayer;
01954             return;
01955         }
01956         BrushComponent *pBrushComp = (BrushComponent*)(pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)));
01957         if (pBrushComp == NULL)
01958         {
01959             ERROR3("Couldn't get brush component");
01960             delete pBrushSpread;
01961             delete pBrushLayer;
01962             return;
01963         }
01964         BrushHandle NewHandle = pBrushComp->AddNewItem(pBrushDef, TRUE);
01965         
01966         if (NewHandle != BrushHandle_NoBrush)
01967         {
01968             if (pInfoBarOp != NULL)
01969                 pInfoBarOp->AddBrush();
01970 
01971             // we want this brush selected
01972             BrushSelected(NewHandle, FALSE);
01973 
01974             // and we want to clear the document selection
01975             NodeRenderableInk::DeselectAll();
01976         }
01977         else
01978             delete pBrushDef;
01979         
01980 }

BOOL FreeHandTool::DeletePaths  )  [protected]
 

Deletes the paths that hold the track data and the smoothed path and sets thier params to NULL.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/5/95
Returns:
TRUE - always

Definition at line 1684 of file freehand.cpp.

01685 {
01686     // Retro fitting is no longer an option
01687     PreviousPathInvalid();
01688 
01689     // Clear out the old Track Data
01690     if (TrackData!=NULL)
01691     {
01692         delete TrackData;
01693         TrackData = NULL;
01694     }
01695     // Clear out the smoothed version of the path
01696     if (RetroPath!=NULL)
01697     {
01698         delete RetroPath;
01699         RetroPath = NULL;
01700     }
01701     // always return TRUE at present
01702     return TRUE;
01703 }

void FreeHandTool::Describe void *  InfoPtr  )  [virtual]
 

Allows the tool manager to extract information about the tool.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93
Parameters:
InfoPtr - A pointer to a tool info block. It is passed cast to void* as [INPUTS] the version of the tool is unknown at this point. Later versions of the Tool class may have more items in this block, that this tool will not use
InfoPtr - The structure pointed to by InfoPtr will have had all the info [OUTPUTS] that this version of the Tool knows about

Reimplemented from Tool_v1.

Definition at line 368 of file freehand.cpp.

00369 {
00370     // Cast structure into the latest one we understand.
00371     ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr;
00372 
00373     Info->InfoVersion = 1;
00374     Info->InterfaceVersion = GetToolInterfaceVersion();  // You should always have this line.
00375         
00376     // These are all arbitrary at present.
00377     Info->Version = 1;
00378     Info->ID      = GetID();
00379     Info->TextID  = _R(IDS_FREE_HAND_TOOL);
00380     Info->BubbleID = _R(IDBBL_FHND_TOOLBOX);
00381 
00382     Info->Family  = FamilyName;
00383     Info->Name    = ToolName;
00384     Info->Purpose = Purpose;
00385     Info->Author  = Author;
00386 
00387     Info->InfoBarDialog = _R(IDD_FREEHANDTOOL);
00388 }

GRenderBrush * FreeHandTool::GetBigGRenderBrush Spread pSpread  )  [protected]
 

Gets a GRenderBrush the size of the current view, then renders into it the contents of the current view.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/99
Returns:
-

Definition at line 2081 of file freehand.cpp.

02082 {
02083 PORTNOTE("other", "Removed m_pGRenderBrush support");
02084 #ifndef EXCLUDE_FROM_XARALX
02085     m_bBrushReady = FALSE;
02086     Document* pDoc = Document::GetSelected();
02087     if (!pDoc)
02088         return NULL;
02089 
02090     DocView * pDocView = DocView::GetSelected();
02091     
02092     // get the docview rect and convert to spread coords 
02093     DocRect ViewRect = pDocView->GetDocViewRect(pSpread);
02094     pSpread->DocCoordToSpreadCoord(&ViewRect);
02095     
02096     // find out about our device 
02097     //View* pView = View::GetSelectedView();
02098     CCamView* pCCamView = pDocView->GetConnectionToOilView(); 
02099     CDC* pDevContext = ((ScreenCamView*)pCCamView)->GetRenderDC();
02100     HDC DeviceHdc = pDevContext->GetSafeHdc();
02101     INT32 DeviceBPP = GetDeviceCaps(DeviceHdc, BITSPIXEL);
02102     
02103     // a couple more variables we need to get the GRenderBrush
02104     Matrix  RenderMat = pDocView->ConstructRenderingMatrix(pSpread);    
02105     FIXED16 Scale = 1;
02106 //  INT32 i = 0;
02107     GRenderBrush* pGRender = NULL;  
02108     
02109     INT32 DeviceRes = GetDeviceCaps( DeviceHdc, LOGPIXELSX );
02110     // create a new GRenderBrush at 32BPP and 96 dpi
02111     pGRender = new GRenderBrush(ViewRect, RenderMat, Scale, 32, DeviceRes); 
02112 
02113     // Check to see if the Render Region is valid!
02114     if (pGRender == NULL)
02115     {
02116         ERROR3("Failed to allocate DIB");
02117         return NULL;
02118     }
02119 
02120     BOOL ok = pGRender->AttachDevice(pDocView, pDevContext, pSpread);
02121     if (!ok)
02122     {   
02123         delete pGRender;
02124         pGRender = NULL;    
02125         return NULL;
02126     }
02127     
02128     if (DeviceBPP < 24)
02129         pGRender->SetDeepDIB(FALSE);
02130     else
02131         pGRender->SetDeepDIB(TRUE);
02132 
02133     
02134     pGRender->InitDevice();
02135     pGRender->m_DoCompression = TRUE;
02136     
02137     pGRender->InitAttributes();
02138     pGRender->RRQuality.SetQuality(QUALITY_MAX);
02139     pGRender->SetQualityLevel();
02140     pGRender->SetLineAttributes();
02141     pGRender->SetFillAttributes();
02142 
02143 
02144     // lleeeets geeet ready to render!  
02145     if (!pGRender->StartRender())
02146     {
02147         ERROR3("Unable to setup bitmap");
02148         delete pGRender;
02149         return NULL;
02150     }
02151     
02152     // if we're less than 24 bit then we need to allocate smaller brush bitmaps as well
02153     if (DeviceBPP < 24)
02154     {
02155         if (!InitialiseBrushBitmaps(pGRender))
02156         {
02157             InformWarning(_R(IDS_BRUSHBITMAP_INVALID));
02158             delete pGRender;
02159             return NULL;
02160         }
02161     }
02162 
02163     // or blit, in this case, as it is quicker than rendering the view
02164     if (!pGRender->CaptureView(pSpread))
02165     {
02166         ERROR3("Unable to capture view");
02167         delete pGRender;
02168         return NULL;
02169     }
02170 
02171 
02172     m_bBrushReady = TRUE;
02173     return pGRender;
02174 #else
02175     return NULL;
02176 #endif
02177 }

BrushHandle FreeHandTool::GetBrushHandle void   )  [inline]
 

Definition at line 219 of file freehand.h.

00219 { return m_BrushHandle;}

MILLIPOINT FreeHandTool::GetBrushSpacing  ) 
 

for finding out the freehand tools current brush spacing

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/11/99
Returns:
The current brush spacing

Definition at line 2191 of file freehand.cpp.

02192 {
02193     return m_BrushSpacing;
02194 }

UINT32 FreeHandTool::GetID  )  [virtual]
 

Reimplemented from Tool_v1.

Definition at line 391 of file freehand.cpp.

00392 {
00393     return TOOLID_FREEHAND;
00394 }

FreeHandInfoBarOp* FreeHandTool::GetInfoBar  )  [inline]
 

Definition at line 199 of file freehand.h.

00199 { return pInfoBarOp;}

DocRect FreeHandTool::GetLargestInkBoundingRect  )  [protected]
 

as above, note that the m_brushinknodes pointer must be initialised

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/99
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
the bounding rect of the largest brush ink object, or an empty rect

Definition at line 2263 of file freehand.cpp.

02264 {
02265     DocRect LargestBRect;  //create an empty rect
02266 
02267     
02268 
02269     INT32 BiggestArea = 0;
02270     for (UINT32 i = 0; i < m_NumInkNodes; i++)
02271     {
02272         DocRect TempRect = m_BrushInkNodeArray[i]->GetBoundingRect();
02273         INT32 TempArea = TempRect.Height() * TempRect.Width();
02274         if (TempArea > BiggestArea)
02275         {
02276             LargestBRect = TempRect;
02277             BiggestArea  = TempArea;
02278         }
02279     }
02280     return LargestBRect;
02281 }

BOOL FreeHandTool::GetNewPaths  )  [protected]
 

Gets rid of the old path data and creates new paths. One of the useful side effects of doing this is that it helps to keep the path data near the top of the heap, make the freehand tool seem more responsive.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/5/95
Returns:
TRUE if everything worked like a dream, FALSE if it screwed up big time

Definition at line 1628 of file freehand.cpp.

01629 {
01630     // Delete the paths that we have
01631     DeletePaths();
01632 
01633     // Create some new paths
01634