#include <pathedit.h>
Inheritance diagram for OpNodePathEditBlob:
Public Member Functions | |
OpNodePathEditBlob () | |
void | DoStartDragEdit (NodePath *, DocCoord Anchor, Spread *) |
This is called to start a drag operation on an endpoint on a path. | |
virtual void | DragPointerMove (DocCoord Pos, ClickModifiers Mods, Spread *pSpread, BOOL bSolidDrag) |
This is called every time the mouse moves, during a drag. | |
virtual void | DragFinished (DocCoord Pos, ClickModifiers Mods, Spread *pSpread, BOOL Success, BOOL bSolidDrag) |
This is called when a drag operation finishes. | |
virtual void | RenderDragBlobs (DocRect, Spread *, BOOL bSolidDrag) |
Renders the new version of the path to the window. It makes use of flags in the path to determine which segments of the path need to be rendered. | |
Static Public Member Functions | |
static BOOL | Init () |
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. | |
Protected Member Functions | |
BOOL | BuildEditPath () |
Builds a copy of the path that we can edit, without destroying the original data. Also sets the NeedToRender flags for EOR display. | |
BOOL | BuildEditPaths () |
Builds a copy of each path in the selection that we can edit, without destroying the original data. Also sets the NeedToRender flags for EOR display. | |
BOOL | CopyEditedPathBack () |
Copies the contents of the edited path back into the original path. | |
BOOL | CopyEditedPathBack (NodePath *pOrigPath, Path *pEditPath) |
Copies the contents of the edited path back into the original path. | |
BOOL | CopyNeedToRenderFlags () |
This function is used to copy the NeedToRender flags from EditPath to OriginalPath. This are then used in optimised region invalidation. | |
BOOL | CopyNeedToRenderFlags (NodePath *pOrigPath, Path *pEditPath) |
This function is used to copy the NeedToRender flags from EditPath to OriginalPath. This are then used in optimised region invalidation. | |
void | RecalculatePath (DocCoord Offset, BOOL SnapEnds=FALSE, INT32 SnapIndex=0) |
This goes through the path, moves all the selected coords by the offset and then performs some magic to smooth the rest of the path round the changes if it needs it. | |
void | RecalculatePaths (Path *pEditPath, DocCoord Offset, BOOL SnapEnds=FALSE, INT32 SnapIndex=0) |
This goes through the path, moves all the selected coords by the offset and then performs some magic to smooth the rest of the path round the changes if it needs it. | |
void | SnapEndsTogether () |
Sets the closefigure flag in the last element in the subpath. Also turns off the rotate bit in the points we're snapping together if their smoothing bits are also turned off. This prevents us creating a cusp that has rotate flags set. | |
void | SnapEndsTogether (Path *pEditPath) |
Sets the closefigure flag in the last element in the subpath. Also turns off the rotate bit in the points we're snapping together if their smoothing bits are also turned off. This prevents us creating a cusp that has rotate flags set. | |
BOOL | JoinWithOtherPath () |
Looks at the member variables dealing with snapping to another path and joins the paths together. It will always join the other path to the original path, keeping the original path's attributes intact. NOTE: This routine will alter the OriginalPath member variable if it joins paths, because it has to make a copy of the path for undo purposes. | |
BOOL | JoinWithOtherPath (NodePath **pOrigPath) |
Looks at the member variables dealing with snapping to another path and joins the paths together. It will always join the other path to the original path, keeping the original path's attributes intact. NOTE: This routine will alter the OriginalPath member variable if it joins paths, because it has to make a copy of the path for undo purposes. | |
BOOL | FillPathIfEndsSnapped () |
Will look at the EndSnapped flag and set the IsFilled bit in the OriginalPath Builds undo information. Returns FALSE if it couldn't build the Undo info. | |
BOOL | FillPathIfEndsSnapped (NodePath *pOrigPath) |
Will look at the EndSnapped flag and set the IsFilled bit in the OriginalPath Builds undo information. Returns FALSE if it couldn't build the Undo info. | |
virtual void | RenderDraggingBlobs (DocRect, Spread *) |
Call this function to render all the blobs on screen from this operation. | |
virtual void | RenderDraggingBlobs (Path *pEditPath, Spread *) |
Call this function to render all the blobs on screen from this operation. | |
void | RenderPathEditBlobs (DocRect Rect, Spread *pSpread) |
void | RenderPathEditBlobs (Path *pEditPath, Spread *pSpread) |
Call this function to render all the blobs on screen from this operation. | |
virtual void | SetStatusLineHelp () |
Updates the status line message to reflect the current situation. | |
NodeGroup * | GetGroupParentOfCurve () |
To determine if the current selection is a blend on a curve. | |
NodeGroup * | GetGroupParentOfCurve (NodePath *pOrigPath) |
To determine if the current selection is a blend on a curve. | |
BOOL | InsertChangeBlendStepsAction (NodeBlend *pNodeBlend) |
To adjust the number of steps in a blend on a path as a result of the path being edited (which is why its here rather than in the blend code). First the number of steps is calculated from the new path distance and if different a new action is inserted. | |
AttrBrushType * | GetAppliedBrush () |
To get the brush attribute that is applied to the nodepath we are editing. | |
virtual BOOL | EditBrushAttribute (INT32 FirstIndex, INT32 LastIndex, AttrBrushType *pAttrBrush) |
If we use the shape editor to edit a nodepath with an applied brush attribute and this brush attribute makes use of sampled pressure or time information then the brush needs to resample its data. So here we will insert a few actions to make that happen. | |
MILLIPOINT | GetLengthOfPathSection (Path *pPath, INT32 FirstIndex, INT32 LastIndex) |
As above, if you want to know the distance between two points on the edit path then this function is for you. | |
MILLIPOINT | GetDistanceToPathIndex (Path *pPath, INT32 Index) |
As above,. | |
void | ChangeCursor (Cursor *cursor) |
Changes the mouse pointer to a new shape. | |
BOOL | CreateCursors () |
Creates the cursor objects for the path operations. | |
void | DestroyCursors () |
Deletes the path operation cursors. | |
Protected Attributes | |
Spread * | StartSpread |
DocCoord | StartMousePos |
DocCoord | LastMousePos |
DocCoord | ConstrainPoint |
DocCoord | ConstrainPrevPoint |
DocCoord | ConstrainNextPoint |
NodePath * | OriginalPath |
Path | EditPath |
List | OriginalPaths |
List | EditPaths |
List | PathsDragStarted |
BOOL | MultiplePaths |
BOOL | EndSnapped |
BOOL | SnapToAnother |
NodePath * | SnapToPath |
INT32 | SnapToIndex |
BOOL | SnapToLineOrCurve |
DocCoord | SnapToCoords [4] |
Cursor * | pMoveCursor |
Cursor * | pCloseCursor |
Cursor * | pCrossHairCursor |
Cursor * | MyCurrentCursor |
INT32 | CurrentCursorID |
ObjChangePathEdit | EditObjChange |
List | ObjChanges |
INT32 | DragPoint |
INT32 | UpdatePoint |
BOOL | DragStarted |
Definition at line 143 of file pathedit.h.
|
|
|
Builds a copy of the path that we can edit, without destroying the original data. Also sets the NeedToRender flags for EOR display.
Reimplemented in OpNodePathEditControlBlob, and OpReshapeOrAddPoint. Definition at line 2197 of file pathedit.cpp. 02198 { 02199 // Make a copy of the original path 02200 UINT32 NumCoords = OriginalPath->InkPath.GetNumCoords(); 02201 if (!EditPath.Initialise(NumCoords, 24)) 02202 return FALSE; 02203 if (!EditPath.CopyPathDataFrom(&(OriginalPath->InkPath))) 02204 return FALSE; 02205 02206 // Go though all the coords, with scary amounts of looking back and forwards 02207 UINT32 LastEndPoint = 0; // The EndPoint before this one 02208 BOOL SetNextEndPoint = FALSE; // TRUE if we want to set the next EndPoint to render 02209 BOOL SetNextNextEndPoint = FALSE; // TRUE if we want the one after the next one to render 02210 PathFlags* Flags = EditPath.GetFlagArray(); 02211 for (UINT32 i=0; i<NumCoords; i++) 02212 { 02213 // Make all the flags FALSE by default 02214 Flags[i].NeedToRender = FALSE; 02215 02216 if (Flags[i].IsEndPoint) 02217 { 02218 // if the endpoint 2 elements back was selected and the last element was smooth 02219 // then we need to mark this point for rendering 02220 if (SetNextNextEndPoint) 02221 { 02222 Flags[i].NeedToRender = TRUE; 02223 SetNextNextEndPoint = FALSE; 02224 } 02225 02226 // We have found an Endpoint, do we want to mark this one as renderable 02227 if (SetNextEndPoint) 02228 { 02229 // As the last element was selected, this element needs to render 02230 Flags[i].NeedToRender = TRUE; 02231 SetNextEndPoint = FALSE; 02232 02233 // If the smooth flag is set then the next item needs to render as well 02234 if (Flags[i].IsRotate || Flags[i].IsSmooth) 02235 SetNextNextEndPoint = TRUE; 02236 } 02237 02238 // If its selected, then its renderable 02239 if (Flags[i].IsSelected) 02240 { 02241 Flags[i].NeedToRender = TRUE; 02242 if (Flags[LastEndPoint].IsRotate || Flags[LastEndPoint].IsSmooth) 02243 Flags[LastEndPoint].NeedToRender = TRUE; 02244 02245 // Set the flag for the next endpoint 02246 SetNextEndPoint = TRUE; 02247 } 02248 02249 LastEndPoint = i; 02250 } 02251 } 02252 02253 return TRUE; 02254 }
|
|
Builds a copy of each path in the selection that we can edit, without destroying the original data. Also sets the NeedToRender flags for EOR display.
Definition at line 2107 of file pathedit.cpp. 02108 { 02109 NodeListItem* pCurrent = (NodeListItem*) OriginalPaths.GetHead (); 02110 02111 while (pCurrent) 02112 { 02113 NodePath* pCurrentPath = (NodePath*) (pCurrent->pNode); 02114 Path* NewEditPath = new Path (); 02115 02116 UINT32 NumCoords = pCurrentPath->InkPath.GetNumCoords(); 02117 02118 if (!NewEditPath->Initialise(NumCoords, 24)) 02119 return FALSE; 02120 if (!NewEditPath->CopyPathDataFrom(&(pCurrentPath->InkPath))) 02121 return FALSE; 02122 02123 // Go though all the coords, with scary amounts of looking back and forwards 02124 UINT32 LastEndPoint = 0; // The EndPoint before this one 02125 BOOL SetNextEndPoint = FALSE; // TRUE if we want to set the next EndPoint to render 02126 BOOL SetNextNextEndPoint = FALSE; // TRUE if we want the one after the next one to render 02127 PathFlags* Flags = NewEditPath->GetFlagArray(); 02128 02129 for (UINT32 i=0; i<NumCoords; i++) 02130 { 02131 // Make all the flags FALSE by default 02132 Flags[i].NeedToRender = FALSE; 02133 02134 if (Flags[i].IsEndPoint) 02135 { 02136 // if the endpoint 2 elements back was selected and the last element was smooth 02137 // then we need to mark this point for rendering 02138 if (SetNextNextEndPoint) 02139 { 02140 Flags[i].NeedToRender = TRUE; 02141 SetNextNextEndPoint = FALSE; 02142 } 02143 02144 // We have found an Endpoint, do we want to mark this one as renderable 02145 if (SetNextEndPoint) 02146 { 02147 // As the last element was selected, this element needs to render 02148 Flags[i].NeedToRender = TRUE; 02149 SetNextEndPoint = FALSE; 02150 02151 // If the smooth flag is set then the next item needs to render as well 02152 if (Flags[i].IsRotate || Flags[i].IsSmooth) 02153 SetNextNextEndPoint = TRUE; 02154 } 02155 02156 // If its selected, then its renderable 02157 if (Flags[i].IsSelected) 02158 { 02159 Flags[i].NeedToRender = TRUE; 02160 if (Flags[LastEndPoint].IsRotate || Flags[LastEndPoint].IsSmooth) 02161 Flags[LastEndPoint].NeedToRender = TRUE; 02162 02163 // Set the flag for the next endpoint 02164 SetNextEndPoint = TRUE; 02165 } 02166 02167 LastEndPoint = i; 02168 } 02169 } 02170 02171 NodeListItem* pInsert = new NodeListItem; 02172 pInsert->pNode = (Node*) NewEditPath; 02173 02174 EditPaths.AddTail (pInsert);//NewEditPath); 02175 02176 pCurrent = (NodeListItem*) OriginalPaths.GetNext (pCurrent); 02177 02178 //delete (pInsert); 02179 02180 // delete (NewEditPath); // cleanup that is necessary 02181 } 02182 02183 return (TRUE); 02184 }
|
|
Changes the mouse pointer to a new shape.
Definition at line 4787 of file pathedit.cpp. 04788 { 04789 if (cursor != MyCurrentCursor) 04790 { // only change if this cursor is different from the current cursor 04791 if (MyCurrentCursor != NULL) 04792 { // If one of our cursors is on the stack then get it off 04793 CursorStack::GPop(CurrentCursorID); 04794 } 04795 MyCurrentCursor = cursor; 04796 CurrentCursorID = CursorStack::GPush(cursor); 04797 } 04798 }
|
|
Copies the contents of the edited path back into the original path.
Definition at line 2441 of file pathedit.cpp. 02442 { 02443 // Now to do some undo information. To do this, I have to look at each element in the path 02444 // and each element in the copy, and see which ones differ. I then have to work out how many 02445 // elements that was, and create a path to contain those elements, along with an array of indices 02446 // telling me where those elements came from 02447 INT32 NumElements = pOrigPath->InkPath.GetNumCoords(); 02448 PathVerb* SourceVerbs = pOrigPath->InkPath.GetVerbArray(); 02449 DocCoord* SourceCoords = pOrigPath->InkPath.GetCoordArray(); 02450 PathFlags* SourceFlags = pOrigPath->InkPath.GetFlagArray(); 02451 PathVerb* DestVerbs = pEditPath->GetVerbArray(); 02452 DocCoord* DestCoords = pEditPath->GetCoordArray(); 02453 PathFlags* DestFlags = pEditPath->GetFlagArray(); 02454 02455 INT32 ChangedElements = 0; 02456 INT32 i; 02457 02458 for (i=0;i<NumElements;i++) 02459 { 02460 if (SourceVerbs[i] != DestVerbs[i] || 02461 SourceCoords[i] != DestCoords[i] || 02462 SourceFlags[i] != DestFlags[i] 02463 ) 02464 ChangedElements++; 02465 } 02466 02467 // ChangedElements is the number of elements in this path that will change. 02468 // We have to create three arrays to contain the changed elements, plus one array 02469 // to tell me where the elements should go (the indices) 02470 02471 // I also have to create an action object to contain these arrays. I have to create the action 02472 // object first because that does all the work of deciding if there's enough memory in the 02473 // undo buffer to store the action, and prompting the user accordingly of there isn't 02474 02475 if (ChangedElements > 0) 02476 { 02477 ModifyPathAction* ModAction; 02478 02479 ActionCode Act; 02480 Act = ModifyPathAction::Init(this, &UndoActions, ChangedElements, (Action**)(&ModAction)); 02481 if (Act == AC_FAIL) 02482 { 02483 FailAndExecute(); 02484 End(); 02485 return FALSE; 02486 } 02487 02488 PathVerb* ChangedVerbs=NULL; 02489 DocCoord* ChangedCoords=NULL; 02490 PathFlags* ChangedFlags=NULL; 02491 INT32* ChangedIndices=NULL; 02492 02493 // If the function returned AC_NO_RECORD we shouldn't record any undo information in the action 02494 // NOTE - during unwind all actions return AC_OK with a NULL ModAction pointer!! 02495 if ((Act!=AC_NORECORD) && (ModAction!=NULL)) 02496 { 02497 // This next bit is a bit hellish. Any one of these four allocations can fail, in which case 02498 // we have to tidy up afterwards. Cue a lot of nested ifs and elses. 02499 02500 ALLOC_WITH_FAIL(ChangedVerbs,(PathVerb*) CCMalloc(ChangedElements * sizeof(PathVerb)),this); 02501 if (ChangedVerbs) 02502 { 02503 ALLOC_WITH_FAIL(ChangedCoords,(DocCoord*) CCMalloc(ChangedElements * sizeof(DocCoord)),this); 02504 if (ChangedCoords) 02505 { 02506 ALLOC_WITH_FAIL(ChangedFlags,(PathFlags*) CCMalloc(ChangedElements * sizeof(PathFlags)),this); 02507 if (ChangedFlags) 02508 { 02509 ALLOC_WITH_FAIL(ChangedIndices,(INT32*) CCMalloc(ChangedElements * sizeof(INT32)),this); 02510 if (!ChangedIndices) 02511 { 02512 CCFree( ChangedFlags ); 02513 CCFree( ChangedCoords ); 02514 CCFree( ChangedVerbs); 02515 FailAndExecute(); 02516 End(); 02517 return FALSE; 02518 } 02519 } 02520 else 02521 { 02522 CCFree( ChangedCoords ); 02523 CCFree( ChangedVerbs ); 02524 FailAndExecute(); 02525 End(); 02526 return FALSE; 02527 02528 } 02529 } 02530 else 02531 { 02532 CCFree( ChangedVerbs); 02533 FailAndExecute(); 02534 End(); 02535 return FALSE; 02536 02537 } 02538 } 02539 02540 // Now to put the undo data into the undo action 02541 INT32 index = 0; 02542 for (i=0;i<NumElements;i++) 02543 { 02544 if (SourceVerbs[i] != DestVerbs[i] || 02545 SourceCoords[i] != DestCoords[i] || 02546 SourceFlags[i] != DestFlags[i] 02547 ) 02548 { 02549 ChangedVerbs[index] = SourceVerbs[i]; 02550 ChangedFlags[index] = SourceFlags[i]; 02551 ChangedCoords[index] = SourceCoords[i]; 02552 ChangedIndices[index] = i; 02553 index++; 02554 } 02555 } 02556 02557 // Now we've allocated the arrays, let's tell the action about 'em 02558 ModAction->StoreArrays(ChangedVerbs, ChangedFlags, ChangedCoords, ChangedIndices, pOrigPath); 02559 } 02560 } 02561 02562 if (!pOrigPath->InkPath.CopyPathDataFrom(pEditPath)) 02563 return FALSE; 02564 else 02565 return TRUE; 02566 }
|
|
Copies the contents of the edited path back into the original path.
Definition at line 2269 of file pathedit.cpp. 02270 { 02271 // Now to do some undo information. To do this, I have to look at each element in the path 02272 // and each element in the copy, and see which ones differ. I then have to work out how many 02273 // elements that was, and create a path to contain those elements, along with an array of indices 02274 // telling me where those elements came from 02275 INT32 NumElements = OriginalPath->InkPath.GetNumCoords(); 02276 PathVerb* SourceVerbs = OriginalPath->InkPath.GetVerbArray(); 02277 DocCoord* SourceCoords = OriginalPath->InkPath.GetCoordArray(); 02278 PathFlags* SourceFlags = OriginalPath->InkPath.GetFlagArray(); 02279 PathVerb* DestVerbs = EditPath.GetVerbArray(); 02280 DocCoord* DestCoords = EditPath.GetCoordArray(); 02281 PathFlags* DestFlags = EditPath.GetFlagArray(); 02282 02283 // DY now we want to keep track of the indexes of the changed section 02284 INT32 ChangedElements = 0; 02285 INT32 FirstChanged = -1; 02286 INT32 LastChanged = -1; 02287 02288 INT32 i; 02289 for (i=0;i<NumElements;i++) 02290 { 02291 if (SourceVerbs[i] != DestVerbs[i] || SourceCoords[i] != DestCoords[i] || 02292 SourceFlags[i] != DestFlags[i] ) 02293 { 02294 ChangedElements++; 02295 02296 // if (SourceCoords[i] != DestCoords[i]) 02297 { 02298 // if we have not yet set the first changed index then set it 02299 if (FirstChanged == -1) 02300 FirstChanged = i; 02301 02302 // always set the last changed index 02303 LastChanged = i; 02304 } 02305 } 02306 02307 } 02308 02309 02310 // ChangedElements is the number of elements in this path that will change. 02311 // We have to create three arrays to contain the changed elements, plus one array 02312 // to tell me where the elements should go (the indices) 02313 02314 // I also have to create an action object to contain these arrays. I have to create the action 02315 // object first because that does all the work of deciding if there's enough memory in the 02316 // undo buffer to store the action, and prompting the user accordingly of there isn't 02317 02318 if (ChangedElements > 0) 02319 { 02320 // do the brush editing here 02321 // the following block deals with editing path blobs. For some reason I could not get a 02322 // sensible value for the distance of the edited path from the changed indexes, however 02323 // it works quite nicely by finding the contraining points. 02324 if (DragPoint != -1) 02325 { 02326 // this section only applies for editing blobs (as reshaping has no drag point) 02327 FirstChanged = DragPoint; 02328 LastChanged = DragPoint; 02329 OriginalPath->InkPath.FindPrevEndPoint(&FirstChanged); 02330 OriginalPath->InkPath.FindNextEndPoint(&LastChanged); 02331 } 02332 02333 AttrBrushType* pAttrBrush = GetAppliedBrush(); 02334 if (pAttrBrush != NULL) 02335 EditBrushAttribute(FirstChanged, LastChanged, pAttrBrush); 02336 02337 ModifyPathAction* ModAction; 02338 02339 ActionCode Act; 02340 Act = ModifyPathAction::Init(this, &UndoActions, ChangedElements, (Action**)(&ModAction)); 02341 if (Act == AC_FAIL) 02342 { 02343 FailAndExecute(); 02344 End(); 02345 return FALSE; 02346 } 02347 02348 PathVerb* ChangedVerbs=NULL; 02349 DocCoord* ChangedCoords=NULL; 02350 PathFlags* ChangedFlags=NULL; 02351 INT32* ChangedIndices=NULL; 02352 02353 // If the function returned AC_NO_RECORD we shouldn't record any undo information in the action 02354 // NOTE - during unwind all actions return AC_OK with a NULL ModAction pointer!! 02355 if ((Act!=AC_NORECORD) && (ModAction!=NULL)) 02356 { 02357 // This next bit is a bit hellish. Any one of these four allocations can fail, in which case 02358 // we have to tidy up afterwards. Cue a lot of nested ifs and elses. 02359 02360 ALLOC_WITH_FAIL(ChangedVerbs,(PathVerb*) CCMalloc(ChangedElements * sizeof(PathVerb)),this); 02361 if (ChangedVerbs) 02362 { 02363 ALLOC_WITH_FAIL(ChangedCoords,(DocCoord*) CCMalloc(ChangedElements * sizeof(DocCoord)),this); 02364 if (ChangedCoords) 02365 { 02366 ALLOC_WITH_FAIL(ChangedFlags,(PathFlags*) CCMalloc(ChangedElements * sizeof(PathFlags)),this); 02367 if (ChangedFlags) 02368 { 02369 ALLOC_WITH_FAIL(ChangedIndices,(INT32*) CCMalloc(ChangedElements * sizeof(INT32)),this); 02370 if (!ChangedIndices) 02371 { 02372 CCFree( ChangedFlags ); 02373 CCFree( ChangedCoords ); 02374 CCFree( ChangedVerbs); 02375 FailAndExecute(); 02376 End(); 02377 return FALSE; 02378 } 02379 } 02380 else 02381 { 02382 CCFree( ChangedCoords ); 02383 CCFree( ChangedVerbs ); 02384 FailAndExecute(); 02385 End(); 02386 return FALSE; 02387 02388 } 02389 } 02390 else 02391 { 02392 CCFree( ChangedVerbs); 02393 FailAndExecute(); 02394 End(); 02395 return FALSE; 02396 02397 } 02398 } 02399 02400 // Now to put the undo data into the undo action 02401 INT32 index = 0; 02402 for (i=0;i<NumElements;i++) 02403 { 02404 if (SourceVerbs[i] != DestVerbs[i] || 02405 SourceCoords[i] != DestCoords[i] || 02406 SourceFlags[i] != DestFlags[i] 02407 ) 02408 { 02409 ChangedVerbs[index] = SourceVerbs[i]; 02410 ChangedFlags[index] = SourceFlags[i]; 02411 ChangedCoords[index] = SourceCoords[i]; 02412 ChangedIndices[index] = i; 02413 index++; 02414 } 02415 } 02416 02417 // Now we've allocated the arrays, let's tell the action about 'em 02418 ModAction->StoreArrays(ChangedVerbs, ChangedFlags, ChangedCoords, ChangedIndices, OriginalPath); 02419 } 02420 } 02421 02422 if (!OriginalPath->InkPath.CopyPathDataFrom(&EditPath)) 02423 return FALSE; 02424 else 02425 return TRUE; 02426 }
|
|
This function is used to copy the NeedToRender flags from EditPath to OriginalPath. This are then used in optimised region invalidation.
Definition at line 2618 of file pathedit.cpp. 02619 { 02620 const INT32 OrigLength = pOrigPath->InkPath.GetNumCoords(); 02621 const INT32 EditLength = pEditPath->GetNumCoords(); 02622 02623 if (EditLength != OrigLength) 02624 return FALSE; 02625 02626 PathFlags* EditFlags = pEditPath->GetFlagArray(); 02627 PathFlags* OrigFlags = pOrigPath->InkPath.GetFlagArray(); 02628 02629 for (INT32 loop = 0; loop < EditLength; loop ++) 02630 { 02631 OrigFlags[loop].NeedToRender = EditFlags[loop].NeedToRender; 02632 } 02633 02634 return TRUE; 02635 }
|
|
This function is used to copy the NeedToRender flags from EditPath to OriginalPath. This are then used in optimised region invalidation.
Definition at line 2583 of file pathedit.cpp. 02584 { 02585 const INT32 OrigLength = OriginalPath->InkPath.GetNumCoords(); 02586 const INT32 EditLength = EditPath.GetNumCoords(); 02587 02588 if (EditLength != OrigLength) 02589 return FALSE; 02590 02591 PathFlags* EditFlags = EditPath.GetFlagArray(); 02592 PathFlags* OrigFlags = OriginalPath->InkPath.GetFlagArray(); 02593 02594 for (INT32 loop = 0; loop < EditLength; loop ++) 02595 { 02596 OrigFlags[loop].NeedToRender = EditFlags[loop].NeedToRender; 02597 } 02598 02599 return TRUE; 02600 }
|
|
Creates the cursor objects for the path operations.
Definition at line 4816 of file pathedit.cpp. 04817 { 04818 if (pMoveCursor == NULL) 04819 { // If already created then don't create a new set. 04820 MyCurrentCursor = NULL; 04821 pMoveCursor = new Cursor(TOOLID_BEZTOOL, _R(IDC_MOVEBEZIERCURSOR)); 04822 pCloseCursor = new Cursor(TOOLID_BEZTOOL, _R(IDC_CLOSEPATHCURSOR)); 04823 pCrossHairCursor = new Cursor(TOOLID_BEZTOOL, _R(IDC_CROSSHAIRCURSOR)); 04824 // See if any of them failed 04825 if ((!pMoveCursor || !pMoveCursor->IsValid()) 04826 || (!pCloseCursor || !pCloseCursor->IsValid()) 04827 || (!pCrossHairCursor || !pCrossHairCursor->IsValid())) 04828 { 04829 // They did fail, so clean up 04830 TRACE( _T("Cursors not created in OpNodePathEditBlob::CreateCursors\n")); 04831 delete pMoveCursor; 04832 delete pCloseCursor; 04833 delete pCrossHairCursor; 04834 pMoveCursor = NULL; 04835 return FALSE; 04836 } 04837 } 04838 return TRUE; 04839 }
|
|
Deletes the path operation cursors.
Definition at line 4858 of file pathedit.cpp. 04859 { 04860 if (pMoveCursor != NULL) 04861 { // If one is NULL then the rest don't exist 04862 if (MyCurrentCursor != NULL) 04863 { 04864 CursorStack::GPop(CurrentCursorID); 04865 } 04866 delete pMoveCursor; 04867 delete pCloseCursor; 04868 delete pCrossHairCursor; 04869 pMoveCursor = NULL; 04870 MyCurrentCursor = NULL; 04871 CurrentCursorID = 0; 04872 } 04873 }
|
|
This is called to start a drag operation on an endpoint on a path.
Definition at line 227 of file pathedit.cpp. 00228 { 00229 BOOL Success = TRUE; 00230 00231 // We had better take a note of the starting point of the drag 00232 LastMousePos = Anchor; 00233 StartMousePos = Anchor; 00234 StartSpread = pSpread; 00235 00236 SelRange* theSelection = GetApplication ()->FindSelection (); 00237 00238 BOOL selectionContainsMoulds = FALSE; 00239 00240 if (theSelection) 00241 { 00242 // we need to do some special processing to handle moulds .... 00243 00244 Node* pCurrentNode = (Node*) theSelection->FindFirst (); 00245 00246 while (pCurrentNode) 00247 { 00248 if (IS_A (pCurrentNode, NodeMould)) 00249 { 00250 selectionContainsMoulds = TRUE; 00251 pCurrentNode = NULL; 00252 } 00253 else 00254 { 00255 pCurrentNode = (Node*) theSelection->FindNext (pCurrentNode); 00256 } 00257 } 00258 } 00259 00260 if (!selectionContainsMoulds) 00261 { 00262 BevelTools::BuildListOfSelectedNodes(&OriginalPaths, CC_RUNTIME_CLASS(NodePath)); 00263 } 00264 else 00265 { 00266 // now go and get those moulds baby ! 00267 BevelTools::BuildListOfSelectedNodes(&OriginalPaths, CC_RUNTIME_CLASS(NodeMouldPath)); 00268 00269 // now, we also have to rescan the selection (again!) BUT this time without 00270 // the moulds 00271 00272 Node* pCurrentNode = (Node*) theSelection->FindFirst (); 00273 00274 while (pCurrentNode) 00275 { 00276 if (IS_A (pCurrentNode, NodeMould)) 00277 { 00278 pCurrentNode = (Node*) theSelection->FindNext (pCurrentNode); 00279 } 00280 else 00281 { 00282 if (IS_A (pCurrentNode, NodePath)) 00283 { 00284 NodeListItem* pInsert = new NodeListItem (); 00285 00286 if (pInsert) // and insert into the paths list .... 00287 { 00288 pInsert->pNode = pCurrentNode; 00289 OriginalPaths.AddHead (pInsert); 00290 } 00291 } 00292 00293 pCurrentNode = (Node*) theSelection->FindNext (pCurrentNode); 00294 } 00295 } 00296 } 00297 00298 if (OriginalPaths.GetCount () == 1) 00299 //if (TRUE) 00300 { 00301 MultiplePaths = FALSE; 00302 00303 OriginalPath = OrigPath; 00304 00305 // Now calculate DragPoint and UpdatePoint 00306 if (Success) 00307 { 00308 PathFlags* Flags = OriginalPath->InkPath.GetFlagArray(); 00309 PathVerb* Verbs = OriginalPath->InkPath.GetVerbArray(); 00310 INT32 NumCoords = OriginalPath->InkPath.GetNumCoords(); 00311 00312 for (INT32 i=0;i<NumCoords;i++) 00313 { 00314 if (Flags[i].IsEndPoint && Flags[i].IsSelected 00315 && !(OriginalPath->InkPath.IsSubPathClosed(i) && (Verbs[i] == PT_MOVETO)) ) 00316 { 00317 // If you are dragging a closepoint then you are actually dragging two points 00318 // but we need to update the line tool as the user thinks they are dragging one. 00319 // If we are on the opening moveto then just skip the tests. 00320 if (DragPoint != -1) 00321 { 00322 UpdatePoint = -1; 00323 DragPoint = -1; 00324 break; 00325 } 00326 else 00327 { 00328 UpdatePoint = i; 00329 DragPoint = i; 00330 } 00331 } 00332 } 00333 // On exit from that loop, DragPoint = -1 if there are multiple selected endpoints, 00334 // otherwise DragPoint is the index to the selected endpoint. UpdatePoint is the 00335 // index of the point displaied in the Line tool 00336 } 00337 00338 // Set the constrain point 00339 if (DragPoint != -1) 00340 { 00341 ConstrainPoint = OriginalPath->InkPath.GetCoordArray()[DragPoint]; 00342 00343 // Get the previous endpoint 00344 INT32 OtherEndpoint = DragPoint; 00345 if (OriginalPath->InkPath.FindPrevEndPoint(&OtherEndpoint)) 00346 ConstrainPrevPoint = OriginalPath->InkPath.GetCoordArray()[OtherEndpoint]; 00347 else 00348 ConstrainPrevPoint = ConstrainPoint; 00349 00350 // Get the next endpoint 00351 OtherEndpoint = DragPoint; 00352 if (OriginalPath->InkPath.FindNextEndPoint(&OtherEndpoint)) 00353 ConstrainNextPoint = OriginalPath->InkPath.GetCoordArray()[OtherEndpoint]; 00354 else 00355 ConstrainNextPoint = ConstrainPoint; 00356 } 00357 else 00358 { 00359 ConstrainPoint = Anchor; 00360 ConstrainPrevPoint = Anchor; 00361 ConstrainNextPoint = Anchor; 00362 } 00363 00364 // We also need to make a version of the path that we can change 00365 Success = BuildEditPath(); 00366 00367 // Create and send a change message about this path edit 00368 // This one is handled by moulds in their OnChildChange() function 00369 if (Success) 00370 Success = (EditObjChange.ObjChangeStarting(OrigPath,this,&EditPath,StartSpread,TRUE) == CC_OK); 00371 00372 // Create and display the cursors for this operation 00373 if (Success) 00374 Success = CreateCursors(); 00375 if (Success) 00376 ChangeCursor(pCrossHairCursor); 00377 00378 // // Render the bits of the path that are different 00379 DocRect EditPathBBox = EditPath.GetBoundingRect(); 00380 // if (Success) 00381 // RenderPathEditBlobs(EditPathBBox, pSpread); 00382 00383 // Tell the Dragging system that we need drags to happen 00384 if (Success) 00385 Success = StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos); 00386 00387 if (!Success) 00388 { 00389 InformError(); 00390 FailAndExecute(); 00391 End(); 00392 } 00393 } 00394 else 00395 { 00396 // lets try and keep things the same for the blobs parent as in the one selection case 00397 // BUT lets also try and do our extra stuff .... I expect time MUCK UPS to occur !!!! 00398 00399 MultiplePaths = TRUE; 00400 00401 OriginalPath = OrigPath; 00402 00403 // we need to make OrigPath the first one in our linked list .... 00404 00405 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 00406 00407 while (pCurrentOrig) 00408 { 00409 NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 00410 00411 if (pOrigPath == OrigPath) 00412 { 00413 NodeListItem* newHead = (NodeListItem*) OriginalPaths.RemoveItem (pCurrentOrig); 00414 00415 OriginalPaths.AddHead (newHead); 00416 00417 pCurrentOrig = NULL; 00418 } 00419 else 00420 { 00421 pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 00422 } 00423 } 00424 00425 // Now calculate DragPoint and UpdatePoint 00426 if (Success) 00427 { 00428 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 00429 00430 // CGS: while loop taken out since we can only be 'drag sensitive' to the point 00431 // that is actually being dragged 00432 00433 //while (pCurrentOrig) 00434 { 00435 NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 00436 00437 PathFlags* Flags = pOrigPath->InkPath.GetFlagArray(); 00438 PathVerb* Verbs = pOrigPath->InkPath.GetVerbArray(); 00439 INT32 NumCoords = pOrigPath->InkPath.GetNumCoords(); 00440 00441 for (INT32 i=0;i<NumCoords;i++) 00442 { 00443 if (Flags[i].IsEndPoint && Flags[i].IsSelected 00444 && !(pOrigPath->InkPath.IsSubPathClosed(i) && (Verbs[i] == PT_MOVETO)) ) 00445 { 00446 // If you are dragging a closepoint then you are actually dragging two points 00447 // but we need to update the line tool as the user thinks they are dragging one. 00448 // If we are on the opening moveto then just skip the tests. 00449 if (DragPoint != -1) 00450 { 00451 UpdatePoint = -1; 00452 DragPoint = -1; 00453 break; 00454 } 00455 else 00456 { 00457 UpdatePoint = i; 00458 DragPoint = i; 00459 } 00460 } 00461 } 00462 00463 // pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 00464 } 00465 // On exit from that loop, DragPoint = -1 if there are multiple selected endpoints, 00466 // otherwise DragPoint is the index to the selected endpoint. UpdatePoint is the 00467 // index of the point displaied in the Line tool 00468 } 00469 00470 // Set the constrain point - do this only for the path that was clicked on 00471 // Any guesses as to why? 00472 00473 // Answer: cause its the one that is being dragged! 00474 if (DragPoint != -1) 00475 { 00476 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 00477 NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 00478 00479 ConstrainPoint = pOrigPath->InkPath.GetCoordArray()[DragPoint]; 00480 00481 // Get the previous endpoint 00482 INT32 OtherEndpoint = DragPoint; 00483 if (pOrigPath->InkPath.FindPrevEndPoint(&OtherEndpoint)) 00484 ConstrainPrevPoint = pOrigPath->InkPath.GetCoordArray()[OtherEndpoint]; 00485 else 00486 ConstrainPrevPoint = ConstrainPoint; 00487 00488 // Get the next endpoint 00489 OtherEndpoint = DragPoint; 00490 if (pOrigPath->InkPath.FindNextEndPoint(&OtherEndpoint)) 00491 ConstrainNextPoint = pOrigPath->InkPath.GetCoordArray()[OtherEndpoint]; 00492 else 00493 ConstrainNextPoint = ConstrainPoint; 00494 } 00495 else 00496 { 00497 ConstrainPoint = Anchor; 00498 ConstrainPrevPoint = Anchor; 00499 ConstrainNextPoint = Anchor; 00500 } 00501 00502 // We also need to make versions of the paths that we can change 00503 Success = BuildEditPaths(); 00504 00505 // Create and send a change message about this path edit 00506 // This one is handled by moulds in their OnChildChange() function 00507 if (Success) 00508 { 00509 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 00510 NodeListItem* pCurrentEdit = (NodeListItem*) EditPaths.GetHead (); 00511 00512 while ((pCurrentOrig) && (pCurrentEdit)) 00513 { 00514 NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 00515 Path* pEditPath = (Path*) (pCurrentEdit->pNode); 00516 00518 00519 ObjChangePathEdit* NewEditObjChange = new ObjChangePathEdit; 00520 00521 Success = (NewEditObjChange->ObjChangeStarting(pOrigPath,this,pEditPath,StartSpread,TRUE) == CC_OK); 00522 00523 NodeListItem* pInsert = new NodeListItem; 00524 pInsert->pNode = (Node*) NewEditObjChange; 00525 00526 ObjChanges.AddTail (pInsert); 00527 00529 00530 BOOL* NewDragStartVal = new BOOL; 00531 *NewDragStartVal = FALSE; 00532 00533 NodeListItem* pInsert2 = new NodeListItem; 00534 pInsert2->pNode = (Node*) NewDragStartVal; 00535 00536 PathsDragStarted.AddTail (pInsert2); 00537 00539 00540 if (Success) 00541 { 00542 pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 00543 pCurrentEdit = (NodeListItem*) EditPaths.GetNext (pCurrentEdit); 00544 } 00545 else 00546 { 00547 pCurrentOrig = NULL; 00548 pCurrentEdit = NULL; 00549 } 00550 00552 00553 //delete (NewEditObjChange); 00554 // delete (NewDragStartVal); 00555 } 00556 } 00557 00558 // Create and display the cursors for this operation (only once - obviously) 00559 if (Success) 00560 Success = CreateCursors(); 00561 if (Success) 00562 ChangeCursor(pCrossHairCursor); 00563 00564 // // Render the bits of the path that are different 00565 DocRect EditPathBBox;// = EditPath.GetBoundingRect(); 00566 00567 SelRange* Selected = GetApplication()->FindSelection(); 00568 00569 EditPathBBox = Selected->GetBlobBoundingRect (); 00570 00571 // if (Success) 00572 // RenderPathEditBlobs(EditPathBBox, pSpread); 00573 00574 // Tell the Dragging system that we need drags to happen 00575 if (Success) 00576 Success = StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos); 00577 00578 if (!Success) 00579 { 00580 InformError(); 00581 FailAndExecute(); 00582 End(); 00583 } 00584 } 00585 }
|
|
This is called when a drag operation finishes.
Reimplemented from Operation. Reimplemented in OpNodePathAddEndpoint, OpReshapeOrAddPoint, and OpNewPath. Definition at line 1169 of file pathedit.cpp. 01171 { 01172 if (!MultiplePaths) 01173 { 01174 if (DragStarted) 01175 RenderDraggingBlobs( EditPath.GetBoundingRect(), StartSpread ); 01176 DestroyCursors(); 01177 EndDrag(); 01178 BeginSlowJob(); 01179 ChangeCode Chge; 01180 01181 BOOL NotFailed = Success; 01182 01183 // DY, if we are editing a brushed nodepath then we need a couple of extra actions 01184 AttrBrushType* pAttrBrush = GetAppliedBrush(); 01185 01186 if (NotFailed) 01187 { 01188 if (!DragStarted) 01189 { 01190 INT32 i; 01191 if (OriginalPath->InkPath.FindNearestPoint( PointerPos, 01192 POINTFLAG_ENDPOINTS | 01193 POINTFLAG_CONTROLPOINTS | 01194 POINTFLAG_ENDSFIRST, 01195 &i) 01196 ) 01197 { 01198 // Deselect all but the clicked endpoint 01199 OriginalPath->InkPath.RenderPathSelectedControlBlobs(StartSpread); 01200 OriginalPath->InkPath.ClearSubSelection(); 01201 PathFlags* pFlags = OriginalPath->InkPath.GetFlagArray(); 01202 pFlags[i].IsSelected = TRUE; 01203 OriginalPath->InkPath.EnsureSelection(TRUE); 01204 OriginalPath->InkPath.RenderPathSelectedControlBlobs(StartSpread); 01205 01206 // Send a sel-changed message so tools update (hello jason 8-) 01207 GetApplication()->FindSelection()->Update(); 01208 01209 // Kill the op so we dont appear in the undo history 01210 FailAndExecute(); 01211 End(); 01212 return; 01213 } 01214 } 01215 else 01216 { 01217 NotFailed = DoStartSelOp(TRUE,TRUE); 01218 01219 // Create and send a change message about this path edit 01220 if (NotFailed) 01221 { 01222 ObjChangeFlags cFlags; 01223 cFlags.TransformNode = TRUE; 01224 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,OriginalPath,this); 01225 NotFailed = OriginalPath->AllowOp(&ObjChange, TRUE); 01226 } 01227 01228 // // Store the paths sub-selection state 01229 // if (NotFailed) 01230 // NotFailed = (StorePathSubSelStateAction::DoRecord(this, &UndoActions, &OriginalPath->InkPath) != AC_FAIL); 01231 01232 // Check we are dealing with a node path. If not, we shouldn't optimise the redraw. 01233 // Really we should ask the node whether it can cope with optimised redraw. This means 01234 // whether its correct simply to redraw the changed rectangular section around the moved 01235 // coordinate. For envelope and perspective moulds whose shapes are govened by derived 01236 // path objects its not correct to redraw optimally as this can result in sections of the 01237 // object being left undrawn when the whole surface / contents have changed. 01238 BOOL OptimiseRedraw = CopyNeedToRenderFlags() && !(EndSnapped || SnapToAnother); 01239 if (!IS_A(OriginalPath,NodePath)) 01240 OptimiseRedraw = FALSE; 01241 01242 // if we are editing a brush we don't want to optimise either, as it redraws incorrectly 01243 if (pAttrBrush != NULL) 01244 OptimiseRedraw = FALSE; 01245 // We had better copy the path back over the original and re-calc the bounding box 01246 // Force a re-draw of the place where the path used to be 01247 if (NotFailed) 01248 NotFailed = RecalcBoundsAction::DoRecalc(this, &UndoActions, OriginalPath, OptimiseRedraw) != AC_FAIL; 01249 01250 01251 //if we are editing a brushed nodepath we need to have this here for the undo to work 01252 if (pAttrBrush != NULL && pAttrBrush->IsTimeStamping() && NotFailed) 01253 { 01254 UpdateBrushAction* pAction; 01255 NotFailed = (UpdateBrushAction::Init(this, &UndoActions, OriginalPath, &pAction) != AC_FAIL); 01256 } 01257 // If the EndSnapped flag is set, we have to set the PT_CLOSEFIGURE flag in the last 01258 // element of the copied path 01259 if (NotFailed && EndSnapped) 01260 SnapEndsTogether(); 01261 01262 // Go and copy the edited path back over the original path 01263 if (NotFailed) 01264 NotFailed = CopyEditedPathBack(); 01265 01266 // If the ends snapped, set the filled bit on the path 01267 if (NotFailed) 01268 NotFailed = FillPathIfEndsSnapped(); 01269 if (NotFailed) 01270 NotFailed = JoinWithOtherPath(); 01271 01272 if (NotFailed) 01273 { 01274 // Recalculate the path's bounding box 01275 OriginalPath->InvalidateBoundingRect(); 01276 SelRange *Sel = GetApplication()->FindSelection(); 01277 Sel->UpdateBounds(); 01278 01279 // Expand the pasteboard as necessary to include the new object bounds 01280 DocRect NewBounds = Sel->GetBoundingRect(TRUE); 01281 ERROR3IF(pSpread == NULL, "Unexpectedly NULL spread pointer"); 01282 pSpread->ExpandPasteboardToInclude(NewBounds); 01283 01284 // Force a redraw of the place where the path is now. 01285 NotFailed = RecordBoundsAction::DoRecord(this, &UndoActions, OriginalPath, OptimiseRedraw) != AC_FAIL; 01286 } 01287 } 01288 } 01289 01290 // DY 9/99 Check to see if we are editing a blend on a curve, if so we may wish to 01291 // change the number of steps in the blend (making use of the path distance). 01292 NodeGroup* pParent = GetGroupParentOfCurve(); 01293 01294 if (pParent != NULL) 01295 { 01296 if (pParent->IS_KIND_OF(NodeBlend)) 01297 { 01298 if (NotFailed) 01299 InsertChangeBlendStepsAction((NodeBlend*)pParent); 01300 } 01301 01302 } 01303 01304 01305 01306 // Inform all the parents of this node that it has been changed. 01307 if (NotFailed) 01308 { 01309 ObjChangeFlags ChgeFlags; 01310 EditObjChange.Define(OBJCHANGE_FINISHED,ChgeFlags,OriginalPath,this,&EditPath,StartSpread); 01311 NotFailed = UpdateChangedNodes(&EditObjChange); 01312 } 01313 else 01314 { 01315 if (EditObjChange.ChangeMask.Finished) 01316 Chge=EditObjChange.ObjChangeFailed(OriginalPath,this,&EditPath,StartSpread,TRUE); 01317 } 01318 01319 01320 if (!NotFailed) 01321 FailAndExecute(); 01322 01323 OriginalPaths.DeleteAll (); 01324 01325 GetApplication()->UpdateSelection(); 01326 End(); 01327 } 01328 else 01329 { 01330 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 01331 NodeListItem* pCurrentEdit = (NodeListItem*) EditPaths.GetHead (); 01332 NodeListItem* pCurrentChange = (NodeListItem*) ObjChanges.GetHead (); 01333 NodeListItem* pCurrentDragS = (NodeListItem*) PathsDragStarted.GetHead (); 01334 01335 DocCoord Offset; 01336 01337 DestroyCursors(); 01338 EndDrag(); 01339 BeginSlowJob(); 01340 ChangeCode Chge; 01341 01342 BOOL NotFailed = Success; 01343 01344 // DY, if we are editing a brushed nodepath then we need a couple of extra actions 01345 AttrBrushType* pAttrBrush = GetAppliedBrush(); 01346 01347 if (NotFailed) 01348 NotFailed = DoStartSelOp(TRUE,TRUE); 01349 01350 while ((pCurrentOrig) && (pCurrentEdit) && (pCurrentChange) && (pCurrentDragS)) 01351 { 01352 NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 01353 Path* pEditPath = (Path*) (pCurrentEdit->pNode); 01354 // ObjChangePathEdit* pObjChange = (ObjChangePathEdit*) (pCurrentChange->pNode); 01355 BOOL* pDragStarted = (BOOL*) (pCurrentDragS->pNode); 01356 01357 if (*pDragStarted == TRUE) 01358 { 01359 RenderDraggingBlobs( pEditPath/*EditPath.GetBoundingRect()*/, StartSpread ); 01360 } 01361 01362 if (NotFailed) 01363 { 01364 if (*pDragStarted == FALSE) 01365 { 01366 INT32 i; 01367 if (pOrigPath->InkPath.FindNearestPoint(PointerPos, 01368 POINTFLAG_ENDPOINTS | 01369 POINTFLAG_CONTROLPOINTS | 01370 POINTFLAG_ENDSFIRST, 01371 &i) 01372 ) 01373 { 01374 // Deselect all but the clicked endpoint 01375 pOrigPath->InkPath.RenderPathSelectedControlBlobs(StartSpread); 01376 pOrigPath->InkPath.ClearSubSelection(); 01377 PathFlags* pFlags = pOrigPath->InkPath.GetFlagArray(); 01378 pFlags[i].IsSelected = TRUE; 01379 pOrigPath->InkPath.EnsureSelection(TRUE); 01380 pOrigPath->InkPath.RenderPathSelectedControlBlobs(StartSpread); 01381 01382 // Send a sel-changed message so tools update (hello jason 8-) 01383 GetApplication()->FindSelection()->Update(); 01384 01385 // Kill the op so we dont appear in the undo history 01386 FailAndExecute(); 01387 End(); 01388 return; 01389 } 01390 } 01391 else 01392 { 01393 //NotFailed = DoStartSelOp(TRUE,TRUE); 01394 01395 // Create and send a change message about this path edit 01396 if (NotFailed) 01397 { 01398 ObjChangeFlags cFlags; 01399 cFlags.TransformNode = TRUE; 01400 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,pOrigPath,this); 01401 NotFailed = pOrigPath->AllowOp(&ObjChange, TRUE); 01402 } 01403 01404 // // Store the paths sub-selection state 01405 // if (NotFailed) 01406 // NotFailed = (StorePathSubSelStateAction::DoRecord(this, &UndoActions, &OriginalPath->InkPath) != AC_FAIL); 01407 01408 // Check we are dealing with a node path. If not, we shouldn't optimise the redraw. 01409 // Really we should ask the node whether it can cope with optimised redraw. This means 01410 // whether its correct simply to redraw the changed rectangular section around the moved 01411 // coordinate. For envelope and perspective moulds whose shapes are govened by derived 01412 // path objects its not correct to redraw optimally as this can result in sections of the 01413 // object being left undrawn when the whole surface / contents have changed. 01414 BOOL OptimiseRedraw = CopyNeedToRenderFlags(pOrigPath, pEditPath) && !(EndSnapped || SnapToAnother); 01415 if (!IS_A(pOrigPath,NodePath)) 01416 OptimiseRedraw = FALSE; 01417 01418 // if we are editing a brush we don't want to optimise either, as it redraws incorrectly 01419 if (pAttrBrush != NULL) 01420 OptimiseRedraw = FALSE; 01421 01422 // We had better copy the path back over the original and re-calc the bounding box 01423 // Force a re-draw of the place where the path used to be 01424 if (NotFailed) 01425 NotFailed = RecalcBoundsAction::DoRecalc(this, &UndoActions, pOrigPath, OptimiseRedraw) != AC_FAIL; 01426 01427 01428 //if we are editing a brushed nodepath we need to have this here for the undo to work 01429 if (pAttrBrush != NULL && pAttrBrush->IsTimeStamping() && NotFailed) 01430 { 01431 UpdateBrushAction* pAction; 01432 NotFailed = (UpdateBrushAction::Init(this, &UndoActions, pOrigPath, &pAction) != AC_FAIL); 01433 } 01434 01435 if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ()) 01436 { 01437 // If the EndSnapped flag is set, we have to set the PT_CLOSEFIGURE flag in the last 01438 // element of the copied path 01439 if (NotFailed && EndSnapped) 01440 { 01441 SnapEndsTogether (pEditPath); 01442 } 01443 } 01444 01445 // Go and copy the edited path back over the original path 01446 if (NotFailed) 01447 NotFailed = CopyEditedPathBack(pOrigPath, pEditPath); 01448 01449 if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ()) 01450 { 01451 // If the ends snapped, set the filled bit on the path 01452 if (NotFailed) 01453 NotFailed = FillPathIfEndsSnapped(pOrigPath); 01454 } 01455 01456 // CGS: BUT, we need to delay the snapping of a control point to another 01457 // paths until here. These is because the path that we are snapping to 01458 // could have also of been dragged; and it is NOT guaranteed to have been 01459 // updated until now .... 01460 01461 BOOL useHeadPath = FALSE; 01462 NodePath* pHeadPath = NULL; 01463 NodePath** hHeadPath = NULL; 01464 01465 if (pOrigPath == SnapToPath) 01466 { 01467 if (NotFailed) 01468 { 01469 NodeListItem* pHeadOrig = (NodeListItem*) OriginalPaths.GetHead (); 01470 /*NodePath**/ pHeadPath = (NodePath*) (pHeadOrig->pNode); 01471 hHeadPath = &pHeadPath; 01472 01473 NotFailed = JoinWithOtherPath(hHeadPath); 01474 01475 if (NotFailed) 01476 { 01477 useHeadPath = TRUE; 01478 } 01479 } 01480 } 01481 01482 if (NotFailed) 01483 { 01484 // Recalculate the path's bounding box 01485 pOrigPath->InvalidateBoundingRect(); 01486 SelRange *Sel = GetApplication()->FindSelection(); 01487 Sel->UpdateBounds(); 01488 01489 // Expand the pasteboard as necessary to include the new object bounds 01490 DocRect NewBounds = Sel->GetBoundingRect(); 01491 ERROR3IF(pSpread == NULL, "Unexpectedly NULL spread pointer"); 01492 pSpread->ExpandPasteboardToInclude(NewBounds); 01493 01494 if (!useHeadPath) 01495 { 01496 // Force a redraw of the place where the path is now. 01497 NotFailed = RecordBoundsAction::DoRecord(this, &UndoActions, pOrigPath, OptimiseRedraw) != AC_FAIL; 01498 } 01499 else 01500 { 01501 //NodeListItem* pHeadOrig = (NodeListItem*) OriginalPaths.GetHead (); 01502 //NodePath* pHeadPath = (NodePath*) (pHeadOrig->pNode); 01503 01504 // Force a redraw of the place where the path is now. 01505 NotFailed = RecordBoundsAction::DoRecord(this, &UndoActions, (*hHeadPath), OptimiseRedraw) != AC_FAIL; 01506 } 01507 } 01508 } 01509 } 01510 01511 // DY 9/99 Check to see if we are editing a blend on a curve, if so we may wish to 01512 // change the number of steps in the blend (making use of the path distance). 01513 NodeGroup* pParent = GetGroupParentOfCurve(pOrigPath); 01514 01515 if (pParent != NULL) 01516 { 01517 if (pParent->IS_KIND_OF(NodeBlend)) 01518 { 01519 if (NotFailed) 01520 InsertChangeBlendStepsAction((NodeBlend*)pParent); 01521 } 01522 } 01523 01524 // Inform all the parents of this node that it has been changed. 01525 if (NotFailed) 01526 { 01527 ObjChangeFlags ChgeFlags; 01528 EditObjChange.Define(OBJCHANGE_FINISHED,ChgeFlags,pOrigPath,this,pEditPath,StartSpread); 01529 NotFailed = UpdateChangedNodes(&EditObjChange); 01530 } 01531 else 01532 { 01533 if (EditObjChange.ChangeMask.Finished) 01534 Chge=EditObjChange.ObjChangeFailed(pOrigPath,this,pEditPath,StartSpread,TRUE); 01535 } 01536 01537 pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 01538 pCurrentEdit = (NodeListItem*) EditPaths.GetNext (pCurrentEdit); 01539 pCurrentChange = (NodeListItem*) ObjChanges.GetNext (pCurrentChange); 01540 pCurrentDragS = (NodeListItem*) PathsDragStarted.GetNext (pCurrentDragS); 01541 } 01542 01543 if (!NotFailed) 01544 FailAndExecute(); 01545 01546 GetApplication()->UpdateSelection(); 01547 01548 // now we need to handle destruction ourselves .... 01549 01550 // pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 01551 pCurrentEdit = (NodeListItem*) EditPaths.GetHead (); 01552 pCurrentChange = (NodeListItem*) ObjChanges.GetHead (); 01553 pCurrentDragS = (NodeListItem*) PathsDragStarted.GetHead (); 01554 01555 while (/*(pCurrentOrig) &&*/ (pCurrentEdit) && (pCurrentChange) && (pCurrentDragS)) 01556 { 01557 // NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 01558 Path* pEditPath = (Path*) (pCurrentEdit->pNode); 01559 ObjChangePathEdit* pObjChange = (ObjChangePathEdit*) (pCurrentChange->pNode); 01560 BOOL* pDragStarted = (BOOL*) (pCurrentDragS->pNode); 01561 01562 // delete (pCurrentOrig->pNode); 01563 delete (pEditPath); 01564 delete (pObjChange); 01565 delete (pDragStarted); 01566 01567 // pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 01568 pCurrentEdit = (NodeListItem*) EditPaths.GetNext (pCurrentEdit); 01569 pCurrentChange = (NodeListItem*) ObjChanges.GetNext (pCurrentChange); 01570 pCurrentDragS = (NodeListItem*) PathsDragStarted.GetNext (pCurrentDragS); 01571 } 01572 01573 OriginalPaths.DeleteAll (); 01574 EditPaths.DeleteAll (); 01575 ObjChanges.DeleteAll (); 01576 PathsDragStarted.DeleteAll (); 01577 01578 End(); 01579 } 01580 }
|
|
This is called every time the mouse moves, during a drag.
Reimplemented from Operation. Reimplemented in OpNodePathEditControlBlob, and OpReshapeOrAddPoint. Definition at line 602 of file pathedit.cpp. 00603 { 00604 if (!MultiplePaths) 00605 { 00606 // If drag has moved onto a different spread, convert the coord to be relative to the 00607 // original spread. 00608 if (pSpread != StartSpread) 00609 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos); 00610 00611 Path TempPath; 00612 00613 // inform the parent a change is happening 00614 if (EditObjChange.ChangeMask.EorBlobs) 00615 { 00616 ChangeCode Chge = EditObjChange.RenderCurrentBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE); 00617 if (Chge!=CC_OK) 00618 return; 00619 // Create a local copy of the edit path 00620 if (!TempPath.Initialise(EditPath.GetNumCoords(), 12)) 00621 return; 00622 TempPath.CopyPathDataFrom(&EditPath); 00623 } 00624 00625 // Rub out the old EORed version of the path 00626 if (DragStarted) 00627 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread ); 00628 else 00629 DragStarted = TRUE; 00630 00631 // Here is where we do all the snapping to grids and endpoints 00632 // and constrain. First we check for snapping to line ends, then 00633 // we check constrain, then we check grid snapping 00634 00635 EndSnapped = FALSE; // TRUE if this point snaps to the other end 00636 SnapToAnother = FALSE; // TRUE if this point snaps to another line end 00637 SnapToLineOrCurve = FALSE; // No snapped other line 00638 00639 // We might be snapping to an endpoint if the point we're dragging around is either 00640 // a moveto, or is the last point in the subpath. We will also only snap if there is 00641 // only one point selected on the path 00642 00643 DocRect PointerBlobRect; 00644 GetApplication()->GetBlobManager()->GetBlobRect(PointerPos,&PointerBlobRect); 00645 00646 DocCoord* Coords = EditPath.GetCoordArray(); 00647 // PathFlags* Flags = EditPath.GetFlagArray(); 00648 PathVerb* Verbs = EditPath.GetVerbArray(); 00649 INT32 NumCoords = EditPath.GetNumCoords(); 00650 00651 INT32 i; 00652 if (DragPoint != -1) 00653 { 00654 // Look to see if the selected point is a real endpoint 00655 if (Verbs[DragPoint] == PT_MOVETO) 00656 { 00657 // This is the start element of the path 00658 i = DragPoint; 00659 if (!EditPath.IsSubPathClosed(i)) 00660 { 00661 INT32 NextEndpoint = i; 00662 if (EditPath.FindNextEndPoint(&NextEndpoint)) 00663 { 00664 EditPath.FindEndElOfSubPath(&i); // i indexes to the end element 00665 00666 // If this sub-path is one element long then closing it is not allowed 00667 if ((i != NextEndpoint) && PointerBlobRect.ContainsCoord(Coords[i])) 00668 { 00669 PointerPos.x = Coords[i].x + LastMousePos.x - Coords[DragPoint].x; 00670 PointerPos.y = Coords[i].y + LastMousePos.y - Coords[DragPoint].y; 00671 EndSnapped = TRUE; 00672 } 00673 } 00674 } 00675 } 00676 else if (DragPoint+1 == NumCoords || Verbs[DragPoint+1] == PT_MOVETO) 00677 { 00678 // This is the last element in the sub-path 00679 i = DragPoint; 00680 if (!EditPath.IsSubPathClosed(i)) 00681 { 00682 INT32 PrevEndpoint = i; 00683 if (EditPath.FindPrevEndPoint(&PrevEndpoint)) 00684 { 00685 EditPath.FindStartOfSubPath(&i); // i is the index of the start of the sub-path 00686 00687 // If this sub-path is one element long then closing it is not allowed 00688 if ((i != PrevEndpoint) && PointerBlobRect.ContainsCoord(Coords[i])) 00689 { 00690 PointerPos.x = Coords[i].x + LastMousePos.x - Coords[DragPoint].x; 00691 PointerPos.y = Coords[i].y + LastMousePos.y - Coords[DragPoint].y; 00692 EndSnapped = TRUE; 00693 } 00694 } 00695 } 00696 } 00697 } 00698 00699 // That detects snapping to the opposite endpoint, but what about snapping to another 00700 // endpoint altogether? Time to check for that eventuality 00701 if (!EndSnapped && DragPoint != -1 && (Verbs[DragPoint] == PT_MOVETO || DragPoint+1 == NumCoords || Verbs[DragPoint+1] == PT_MOVETO) ) 00702 { 00703 // Get a snapshot of the selection 00704 SelRange* Selected = GetApplication()->FindSelection(); 00705 Node* pNode = Selected->FindFirst(); 00706 INT32 SubIndex,SubEnd; 00707 while (pNode) 00708 { 00709 if ((pNode->FindParentSpread() == StartSpread) && 00710 (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodePath)) /*&& 00711 (pNode != OriginalPath)*/ ) 00712 { 00713 Path* ThisPath = &(((NodePath*)pNode)->InkPath); 00714 INT32 ThisNum = ThisPath->GetNumCoords(); 00715 SubIndex = 0; 00716 SubEnd = 0; 00717 while (SubIndex<ThisNum) 00718 { 00719 DocCoord tempStart,tempEnd; 00720 ThisPath->SetPathPosition(SubIndex); // Set the path's internal pos index 00721 if (ThisPath->GetSubPathEnds(&tempStart, &tempEnd)) 00722 { 00723 SubEnd = ThisPath->GetPathPosition(); 00724 // Now SubIndex is the index of the first, and SubEnd is the index 00725 // of the last element (N.B. might be a curveto, in which case add 2) 00726 if (ThisPath->GetVerb() == PT_BEZIERTO) 00727 SubEnd+=2; 00728 00729 BOOL ClosedPath = (ThisPath->GetVerbArray()[SubEnd] & PT_CLOSEFIGURE) ; 00730 00731 // Now compare start and end with pointer position, but not if this 00732 // subpath is the currently dragging subpath 00733 if ( !ClosedPath && 00734 ( (pNode != OriginalPath) || 00735 ((pNode == OriginalPath) && (DragPoint != SubIndex) && (DragPoint != SubEnd)) ) ) 00736 { 00737 if (PointerBlobRect.ContainsCoord(tempStart)) 00738 { 00739 break; 00740 } 00741 if (PointerBlobRect.ContainsCoord(tempEnd)) 00742 { 00743 SubIndex = SubEnd; 00744 break; 00745 } 00746 } 00747 } 00748 else 00749 { 00750 SubEnd = ThisPath->GetPathPosition(); 00751 } 00752 SubIndex = SubEnd+1; // Points at start of next subpath 00753 // or top of whole path 00754 } 00755 // if SubIndex < ThisNum we must have found a matching coord 00756 // so that's what we'll snap to 00757 if (SubIndex < ThisNum) 00758 break; // Exit the outer while condition 00759 } 00760 pNode = Selected->FindNext(pNode); 00761 } 00762 // At this point, if pNode == NULL we haven't snapped to anything 00763 // otherwise pNode is the path we've snapped to, and SubIndex is the index 00764 // of the point we've snapped to 00765 if (pNode) 00766 { 00767 // if the snap to path is the path being edited check that it has the same number of points! 00768 if (((NodePath*)pNode == OriginalPath) && (OriginalPath->InkPath.GetNumCoords() != EditPath.GetNumCoords())) 00769 { 00770 // PATRACE( _T("Attempted to join an edited path!\n")); 00771 // The problem is that if the OriginalPath has been edited by adding an endpoint then 00772 // SnapToIndex will be wrong as it counted along the original path, not the edited one.... 00773 } 00774 else 00775 { 00776 SnapToAnother = TRUE; 00777 SnapToPath = (NodePath*)pNode; 00778 SnapToIndex = SubIndex; 00779 SnapToPath->InkPath.SetPathPosition(SnapToIndex); 00780 PointerPos.x = SnapToPath->InkPath.GetCoord().x + LastMousePos.x - Coords[DragPoint].x; 00781 PointerPos.y = SnapToPath->InkPath.GetCoord().y + LastMousePos.y - Coords[DragPoint].y; 00782 } 00783 } 00784 } 00785 00786 // We don't allow closed paths consiting of two straight segments 00787 if (EndSnapped && NumCoords < 4) 00788 EndSnapped = FALSE; 00789 00790 if ((EndSnapped || SnapToAnother) && (pMoveCursor != NULL)) 00791 ChangeCursor(pCloseCursor); 00792 else 00793 ChangeCursor(pCrossHairCursor); 00794 00795 // Now constrain the mouse point 00796 ERROR3IF(ConstrainPoint == DocCoord(-1,-1),"ConstrainPoint wasn't set"); 00797 ERROR3IF(ConstrainPrevPoint == DocCoord(-1,-1),"ConstrainPrevPoint wasn't set"); 00798 ERROR3IF(ConstrainNextPoint == DocCoord(-1,-1),"ConstrainNextPoint wasn't set"); 00799 if (!EndSnapped && ClickMods.Constrain) 00800 { 00801 if (ClickMods.Adjust) 00802 { 00803 if (ClickMods.Alternative1 || ClickMods.Alternative2) 00804 DocView::ConstrainToAngle(ConstrainNextPoint, &PointerPos); 00805 else 00806 DocView::ConstrainToAngle(ConstrainPrevPoint, &PointerPos); 00807 } 00808 else 00809 DocView::ConstrainToAngle(ConstrainPoint, &PointerPos); 00810 } 00811 00812 // Only snap to grid if we didn't snap to the end of a path 00813 if (!EndSnapped) 00814 DocView::SnapCurrent(StartSpread,&PointerPos); 00815 00816 // This is the bit where we go off and re-calculate the paths position, 00817 // based on how much the mouse has moved 00818 DocCoord Offset; 00819 Offset.x = PointerPos.x - LastMousePos.x; 00820 Offset.y = PointerPos.y - LastMousePos.y; 00821 00822 RecalculatePath(Offset, EndSnapped, DragPoint); 00823 00824 if (EditObjChange.ChangeMask.EorBlobs) 00825 { 00826 ChangeCode Chge = EditObjChange.RenderChangedBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE); 00827 if (Chge!=CC_OK) 00828 { 00829 // replace the old edit path 00830 EditPath.CopyPathDataFrom(&TempPath); 00831 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread ); 00832 return; 00833 } 00834 } 00835 00836 // Update the Last Mouse Position 00837 LastMousePos = PointerPos; 00838 00839 // Draw in the new version of the path 00840 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread ); 00841 00842 // If there is just one selected point being dragged then we should show 00843 // its new position in the line tool infobar. 00844 if (UpdatePoint != -1) 00845 BROADCAST_TO_ALL(PathEditedMsg(&EditPath, pSpread, UpdatePoint)); 00846 00847 SetStatusLineHelp(); 00848 } 00849 else 00850 { 00851 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 00852 NodeListItem* pCurrentEdit = (NodeListItem*) EditPaths.GetHead (); 00853 NodeListItem* pCurrentChange = (NodeListItem*) ObjChanges.GetHead (); 00854 NodeListItem* pCurrentDragS = (NodeListItem*) PathsDragStarted.GetHead (); 00855 00856 DocCoord Offset(0,0); 00857 00858 while ((pCurrentOrig) && (pCurrentEdit) && (pCurrentChange) && (pCurrentDragS)) 00859 { 00860 NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 00861 Path* pEditPath = (Path*) (pCurrentEdit->pNode); 00862 ObjChangePathEdit* pObjChange = (ObjChangePathEdit*) (pCurrentChange->pNode); 00863 BOOL* pDragStarted = (BOOL*) (pCurrentDragS->pNode); 00864 00866 00867 // If drag has moved onto a different spread, convert the coord to be relative to the 00868 // original spread. 00869 if (pSpread != StartSpread) 00870 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos); 00871 00872 Path TempPath; 00873 00874 // inform the parent a change is happening 00875 if (pObjChange->ChangeMask.EorBlobs) 00876 { 00877 ChangeCode Chge = pObjChange->RenderCurrentBlobs(pOrigPath,this,pEditPath,StartSpread,TRUE); 00878 if (Chge!=CC_OK) 00879 return; 00880 // Create a local copy of the edit path 00881 if (!TempPath.Initialise(pEditPath->GetNumCoords(), 12)) 00882 return; 00883 TempPath.CopyPathDataFrom(pEditPath); 00884 } 00885 00886 // Rub out the old EORed version of the path 00887 if (*pDragStarted == TRUE) 00888 { 00889 RenderPathEditBlobs(pEditPath, /*pEditPath->GetBoundingRect(),*/ StartSpread ); 00890 } 00891 else 00892 { 00893 *pDragStarted = TRUE; 00894 // pCurrentDragS->pNode = (Node*) pDragStarted; 00895 } 00896 00897 DocRect PointerBlobRect; 00898 GetApplication()->GetBlobManager()->GetBlobRect(PointerPos,&PointerBlobRect); 00899 00900 DocCoord* Coords = pEditPath->GetCoordArray(); 00901 // PathFlags* Flags = pEditPath->GetFlagArray(); 00902 PathVerb* Verbs = pEditPath->GetVerbArray(); 00903 INT32 NumCoords = pEditPath->GetNumCoords(); 00904 00905 if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ()) 00906 { 00907 // CGS: all of the operations to do with snapping to grid, snapping to opposite 00908 // end point and snapping to another lines endpoint are relevant only for 00909 // that control point that the drag was initiated from .... 00910 00911 // Here is where we do all the snapping to grids and endpoints 00912 // and constrain. First we check for snapping to line ends, then 00913 // we check constrain, then we check grid snapping 00914 00915 EndSnapped = FALSE; // TRUE if this point snaps to the other end 00916 SnapToAnother = FALSE; // TRUE if this point snaps to another line end 00917 SnapToLineOrCurve = FALSE; // No snapped other line 00918 00919 // We might be snapping to an endpoint if the point we're dragging around is either 00920 // a moveto, or is the last point in the subpath. We will also only snap if there is 00921 // only one point selected on the path 00922 00923 INT32 i; 00924 if (DragPoint != -1) 00925 { 00926 // Look to see if the selected point is a real endpoint 00927 if (Verbs[DragPoint] == PT_MOVETO) 00928 { 00929 // This is the start element of the path 00930 i = DragPoint; 00931 if (!pEditPath->IsSubPathClosed(i)) 00932 { 00933 INT32 NextEndpoint = i; 00934 if (pEditPath->FindNextEndPoint(&NextEndpoint)) 00935 { 00936 pEditPath->FindEndElOfSubPath(&i); // i indexes to the end element 00937 00938 // If this sub-path is one element long then closing it is not allowed 00939 if ((i != NextEndpoint) && PointerBlobRect.ContainsCoord(Coords[i])) 00940 { 00941 PointerPos.x = Coords[i].x + LastMousePos.x - Coords[DragPoint].x; 00942 PointerPos.y = Coords[i].y + LastMousePos.y - Coords[DragPoint].y; 00943 EndSnapped = TRUE; 00944 } 00945 } 00946 } 00947 } 00948 else if (DragPoint+1 == NumCoords || Verbs[DragPoint+1] == PT_MOVETO) 00949 { 00950 // This is the last element in the sub-path 00951 i = DragPoint; 00952 if (!pEditPath->IsSubPathClosed(i)) 00953 { 00954 INT32 PrevEndpoint = i; 00955 if (pEditPath->FindPrevEndPoint(&PrevEndpoint)) 00956 { 00957 pEditPath->FindStartOfSubPath(&i); // i is the index of the start of the sub-path 00958 00959 // If this sub-path is one element long then closing it is not allowed 00960 if ((i != PrevEndpoint) && PointerBlobRect.ContainsCoord(Coords[i])) 00961 { 00962 PointerPos.x = Coords[i].x + LastMousePos.x - Coords[DragPoint].x; 00963 PointerPos.y = Coords[i].y + LastMousePos.y - Coords[DragPoint].y; 00964 EndSnapped = TRUE; 00965 } 00966 } 00967 } 00968 } 00969 } 00970 00971 // That detects snapping to the opposite endpoint, but what about snapping to another 00972 // endpoint altogether? Time to check for that eventuality 00973 if (!EndSnapped && DragPoint != -1 && (Verbs[DragPoint] == PT_MOVETO || DragPoint+1 == NumCoords || Verbs[DragPoint+1] == PT_MOVETO) ) 00974 { 00975 // Get a snapshot of the selection 00976 SelRange* Selected = GetApplication()->FindSelection(); 00977 00978 // do something extra in here .... 00979 00980 Node* pNode = Selected->FindFirst(); 00981 INT32 SubIndex,SubEnd; 00982 while (pNode) 00983 { 00985 if ((pNode->FindParentSpread() == StartSpread) && 00986 (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodePath)) /*&& 00987 (pNode != OriginalPath)*/ ) 00988 { 00990 Path* ThisPath = &(((NodePath*)pNode)->InkPath); 00991 INT32 ThisNum = ThisPath->GetNumCoords(); 00992 SubIndex = 0; 00993 SubEnd = 0; 00994 while (SubIndex<ThisNum) 00995 { 00996 DocCoord tempStart,tempEnd; 00997 ThisPath->SetPathPosition(SubIndex); // Set the path's internal pos index 00998 if (ThisPath->GetSubPathEnds(&tempStart, &tempEnd)) 00999 { 01000 SubEnd = ThisPath->GetPathPosition(); 01001 // Now SubIndex is the index of the first, and SubEnd is the index 01002 // of the last element (N.B. might be a curveto, in which case add 2) 01003 if (ThisPath->GetVerb() == PT_BEZIERTO) 01004 SubEnd+=2; 01005 01006 BOOL ClosedPath = (ThisPath->GetVerbArray()[SubEnd] & PT_CLOSEFIGURE) ; 01007 01008 // Now compare start and end with pointer position, but not if this 01009 // subpath is the currently dragging subpath 01010 if ( !ClosedPath && 01011 ( (pNode != OriginalPath) || 01012 ((pNode == OriginalPath) && (DragPoint != SubIndex) && (DragPoint != SubEnd)) ) ) 01013 { 01014 if (PointerBlobRect.ContainsCoord(tempStart)) 01015 { 01016 break; 01017 } 01018 if (PointerBlobRect.ContainsCoord(tempEnd)) 01019 { 01020 SubIndex = SubEnd; 01021 break; 01022 } 01023 } 01024 } 01025 else 01026 { 01027 SubEnd = ThisPath->GetPathPosition(); 01028 } 01029 SubIndex = SubEnd+1; // Points at start of next subpath 01030 // or top of whole path 01031 } 01032 // if SubIndex < ThisNum we must have found a matching coord 01033 // so that's what we'll snap to 01034 if (SubIndex < ThisNum) 01035 break; // Exit the outer while condition 01036 } 01037 pNode = Selected->FindNext(pNode); 01038 } 01039 // At this point, if pNode == NULL we haven't snapped to anything 01040 // otherwise pNode is the path we've snapped to, and SubIndex is the index 01041 // of the point we've snapped to 01042 if (pNode) 01043 { 01044 // if the snap to path is the path being edited check that it has the same number of points! 01045 if (((NodePath*)pNode == pOrigPath) && (pOrigPath->InkPath.GetNumCoords() != pEditPath->GetNumCoords())) 01046 { 01047 // PATRACE( _T("Attempted to join an edited path!\n")); 01048 // The problem is that if the OriginalPath has been edited by adding an endpoint then 01049 // SnapToIndex will be wrong as it counted along the original path, not the edited one.... 01050 } 01051 else 01052 { 01053 SnapToAnother = TRUE; 01054 SnapToPath = (NodePath*)pNode; 01055 SnapToIndex = SubIndex; 01056 SnapToPath->InkPath.SetPathPosition(SnapToIndex); 01057 PointerPos.x = SnapToPath->InkPath.GetCoord().x + LastMousePos.x - Coords[DragPoint].x; 01058 PointerPos.y = SnapToPath->InkPath.GetCoord().y + LastMousePos.y - Coords[DragPoint].y; 01059 } 01060 } 01061 } 01062 01064 01065 // only do the following for the node that the drag was started from .... 01066 01067 //if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ()) 01068 //{ 01069 // We don't allow closed paths consiting of two straight segments 01070 if (EndSnapped && NumCoords < 4) 01071 EndSnapped = FALSE; 01072 01073 if ((EndSnapped || SnapToAnother) && (pMoveCursor != NULL)) 01074 ChangeCursor(pCloseCursor); 01075 else 01076 ChangeCursor(pCrossHairCursor); 01077 //} 01078 01079 // Now constrain the mouse point 01080 ERROR3IF(ConstrainPoint == DocCoord(-1,-1),"ConstrainPoint wasn't set"); 01081 ERROR3IF(ConstrainPrevPoint == DocCoord(-1,-1),"ConstrainPrevPoint wasn't set"); 01082 ERROR3IF(ConstrainNextPoint == DocCoord(-1,-1),"ConstrainNextPoint wasn't set"); 01083 if (!EndSnapped && ClickMods.Constrain) 01084 { 01085 if (ClickMods.Adjust) 01086 { 01087 if (ClickMods.Alternative1 || ClickMods.Alternative2) 01088 DocView::ConstrainToAngle(ConstrainNextPoint, &PointerPos); 01089 else 01090 DocView::ConstrainToAngle(ConstrainPrevPoint, &PointerPos); 01091 } 01092 else 01093 DocView::ConstrainToAngle(ConstrainPoint, &PointerPos); 01094 } 01095 01096 // Only snap to grid if we didn't snap to the end of a path 01097 if (!EndSnapped) 01098 DocView::SnapCurrent(StartSpread,&PointerPos); 01099 } 01100 01101 // This is the bit where we go off and re-calculate the paths position, 01102 // based on how much the mouse has moved 01103 01104 if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ()) 01105 { 01106 Offset.x = PointerPos.x - LastMousePos.x; 01107 Offset.y = PointerPos.y - LastMousePos.y; 01108 } 01109 01110 // need to consider the validness of EndSnapped and DragPoint as well .... 01111 // CSG says: we MUST pass EndSnapped and DragPoint as passed in below, 01112 // since these two values are reserved for the path that the drag was iniated 01113 // on (i.e. the head of our linked list). If we don't do this, then we get 01114 // loads of nasty asserts and errors going off. 01115 RecalculatePaths (pEditPath, Offset, FALSE /*EndSnapped*/, -1 /*DragPoint*/); 01116 01117 if (pObjChange->ChangeMask.EorBlobs) 01118 { 01119 ChangeCode Chge = pObjChange->RenderChangedBlobs(pOrigPath,this,pEditPath,StartSpread,TRUE); 01120 if (Chge!=CC_OK) 01121 { 01122 // replace the old edit path 01123 pEditPath->CopyPathDataFrom(&TempPath); 01124 RenderPathEditBlobs( pEditPath/*->GetBoundingRect()*/, StartSpread ); 01125 return; 01126 } 01127 } 01128 01129 // Update the Last Mouse Position 01130 LastMousePos = PointerPos; 01131 01132 // Draw in the new version of the path 01133 RenderPathEditBlobs( pEditPath/*->GetBoundingRect()*/, StartSpread ); 01134 01135 // If there is just one selected point being dragged then we should show 01136 // its new position in the line tool infobar. 01137 // if (UpdatePoint != -1) 01138 // BROADCAST_TO_ALL(PathEditedMsg(pEditPath, pSpread, UpdatePoint)); 01139 01141 01142 pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 01143 pCurrentEdit = (NodeListItem*) EditPaths.GetNext (pCurrentEdit); 01144 pCurrentChange = (NodeListItem*) ObjChanges.GetNext (pCurrentChange); 01145 pCurrentDragS = (NodeListItem*) PathsDragStarted.GetNext (pCurrentDragS); 01146 } 01147 01148 SetStatusLineHelp(); 01149 } 01150 }
|
|
If we use the shape editor to edit a nodepath with an applied brush attribute and this brush attribute makes use of sampled pressure or time information then the brush needs to resample its data. So here we will insert a few actions to make that happen.
Reimplemented in OpNodePathAddEndpoint. Definition at line 3927 of file pathedit.cpp. 03928 { 03929 if (FirstIndex < 0 || LastIndex < 0 || LastIndex <= FirstIndex || pAttrBrush == NULL) 03930 { 03931 //ERROR3("Invalid inputs to OpNodePathEditBlob::EditBrushAttribute"); 03932 return FALSE; 03933 } 03934 03935 // currently we only have pressure implemented, and if this attribute does not use 03936 // pressure then theres nothing for us to do 03937 CDistanceSampler* pDistSamp = pAttrBrush->GetPressureCache(); 03938 if (pDistSamp == NULL) 03939 return TRUE; // not an error 03940 03941 /* Basically what we want to do here is resample the data that applies to the changed 03942 section of the path, so that we have the same data applying over a different distance. 03943 The way to implement this in an undoable way is this: 03944 1) Find out the new length of the changed section of the path; 03945 2) Ask the sampler to copy out the current data between the changed points; 03946 4) Resample that data over the new length(the sampler can do this for us); 03947 4) Create an action to undoably remove the original section of data from the attribute 03948 5) Create an action to undoably insert the new resampled section; 03949 */ 03950 MILLIPOINT ChangedLength = GetLengthOfPathSection(&EditPath, FirstIndex, LastIndex); 03951 // MILLIPOINT OrigLength = GetLengthOfPathSection(&(OriginalPath->InkPath), FirstIndex, LastIndex); 03952 03953 // Get the distances to the changed indexes in the original path 03954 MILLIPOINT OrigStartDist = GetDistanceToPathIndex(&(OriginalPath->InkPath), FirstIndex); 03955 MILLIPOINT OrigEndDist = GetDistanceToPathIndex(&(OriginalPath->InkPath), LastIndex); 03956 03957 if (OrigStartDist == -1 || OrigEndDist == -1) 03958 { 03959 ERROR3("Error getting distance to index in OpNodePathEditBlob::EditBrushAttribute"); 03960 return FALSE; 03961 } 03962 // we need another sampler to store the section data, needs to be allocated as we're putting 03963 // it into an action later 03964 CDistanceSampler* pSection = new CDistanceSampler; 03965 if (pSection == NULL) 03966 return FALSE; 03967 03968 // Ask the sampler for its data section 03969 BOOL ok = pDistSamp->GetDataSection(OrigStartDist, OrigEndDist, pSection); 03970 if (!ok) 03971 return FALSE; 03972 03973 // ask the section to resample itself 03974 if (!pSection->ReSample(ChangedLength)) 03975 { 03976 delete pSection; 03977 return FALSE; 03978 } 03979 pSection->SetNumItemsFromArraySize(); 03980 03981 INT32 StartPressIndex = pDistSamp->GetInternalIndexFromDistance(OrigStartDist); 03982 INT32 EndPressIndex = pDistSamp->GetInternalIndexFromDistance(OrigEndDist); 03983 INT32 NumIndexes = EndPressIndex - StartPressIndex; 03984 if (StartPressIndex == -1 || EndPressIndex == -1 || NumIndexes <= 0) 03985 { 03986 delete pSection; 03987 return FALSE; 03988 } 03989 03990 // now make a removepoints action 03991 RemovePressurePointsAction* pAction; 03992 03993 if (RemovePressurePointsAction::Init(this, &UndoActions, pAttrBrush, StartPressIndex, NumIndexes, NULL, &pAction) == AC_FAIL) 03994 return FALSE; 03995 03996 // now insert our new points into the attribute 03997 AddPressurePointsAction* pAddAction; 03998 03999 // find out how many points we're inserting 04000 size_t NumAddPoints = pSection->GetNumItems(); 04001 04002 if (AddPressurePointsAction::Init(this, &UndoActions, pAttrBrush, pSection, StartPressIndex, NumAddPoints, &pAddAction) == AC_FAIL) 04003 { 04004 delete pSection; 04005 return FALSE; 04006 } 04007 04008 return TRUE; 04009 }
|
|
Will look at the EndSnapped flag and set the IsFilled bit in the OriginalPath Builds undo information. Returns FALSE if it couldn't build the Undo info.
Definition at line 4922 of file pathedit.cpp. 04923 { 04924 // If the ends snapped, set the filled bit on the path 04925 if (EndSnapped && !(pOrigPath->InkPath.IsFilled)) 04926 { 04927 ModifyFilledAction* pAction; 04928 if (ModifyFilledAction::Init(this, &UndoActions, TRUE, FALSE, pOrigPath, (Action**)(&pAction))== AC_FAIL) 04929 return FALSE; 04930 pOrigPath->InkPath.IsFilled = TRUE; 04931 } 04932 return TRUE; 04933 }
|
|
Will look at the EndSnapped flag and set the IsFilled bit in the OriginalPath Builds undo information. Returns FALSE if it couldn't build the Undo info.
Definition at line 4893 of file pathedit.cpp. 04894 { 04895 // If the ends snapped, set the filled bit on the path 04896 if (EndSnapped && !(OriginalPath->InkPath.IsFilled)) 04897 { 04898 ModifyFilledAction* pAction; 04899 if (ModifyFilledAction::Init(this, &UndoActions, TRUE, FALSE, OriginalPath, (Action**)(&pAction))== AC_FAIL) 04900 return FALSE; 04901 OriginalPath->InkPath.IsFilled = TRUE; 04902 } 04903 return TRUE; 04904 }
|
|
To get the brush attribute that is applied to the nodepath we are editing.
Definition at line 3889 of file pathedit.cpp. 03890 { 03891 if (OriginalPath == NULL) 03892 return NULL; 03893 03894 NodeAttribute* pAttr = NULL; 03895 AttrBrushType* pAttrBrush = NULL; 03896 OriginalPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr); 03897 03898 if (pAttr != NULL) 03899 { 03900 // just check that our applied brush isn't the default 03901 if (((AttrBrushType*)pAttr)->GetBrushHandle() != BrushHandle_NoBrush) 03902 pAttrBrush = (AttrBrushType*)pAttr; 03903 } 03904 return pAttrBrush; 03905 }
|
|
As above,.
Definition at line 4088 of file pathedit.cpp. 04089 { 04090 // some checks 04091 ERROR2IF(pPath == NULL, -1, "Path is NULL in OpNodePathEditBlob::GetDistanceToPathIndex"); 04092 04093 if (Index >= pPath->GetNumCoords()) 04094 { 04095 ERROR3("Invalid index in OpNodePathEditBlob::GetDistanceToPathIndex"); 04096 return -1; 04097 } 04098 04099 // get the coordinates 04100 DocCoord* pCoords = pPath->GetCoordArray(); 04101 ERROR2IF(pCoords == NULL, -1, "Failed to get coord array in OpNodePathEditBlob::GetLengthOfEditSection"); 04102 04103 DocCoord Coord = pCoords[Index]; 04104 04105 MILLIPOINT Distance = -1; 04106 if (!pPath->GetDistanceToPoint(Coord, &Distance)) 04107 return -1; 04108 04109 return Distance; 04110 }
|
|
To determine if the current selection is a blend on a curve.
Definition at line 3852 of file pathedit.cpp. 03853 { 03854 if (pOrigPath == NULL) 03855 return NULL; 03856 Node* pParent = pOrigPath->FindParent(); 03857 03858 if (pParent != NULL) 03859 { 03860 if (pParent->IS_KIND_OF(NodeBlend)) 03861 { 03862 return (NodeGroup*)pParent; 03863 } 03864 else 03865 return NULL; 03866 } 03867 03868 return NULL; 03869 03870 }
|
|
To determine if the current selection is a blend on a curve.
Definition at line 3815 of file pathedit.cpp. 03816 { 03817 if (OriginalPath == NULL) 03818 return NULL; 03819 Node* pParent = OriginalPath->FindParent(); 03820 03821 if (pParent != NULL) 03822 { 03823 if (pParent->IS_KIND_OF(NodeBlend)) 03824 { 03825 return (NodeGroup*)pParent; 03826 } 03827 else 03828 return NULL; 03829 } 03830 03831 return NULL; 03832 03833 }
|
|
As above, if you want to know the distance between two points on the edit path then this function is for you.
Definition at line 4035 of file pathedit.cpp. 04036 { 04037 ERROR2IF(pPath == NULL, -1, "Path is NULL in OpNodePathEditBlob::GetLengthOfPathSection"); 04038 04039 // find out how many elements there are in EditPath 04040 INT32 NumElements = pPath->GetNumCoords(); 04041 04042 // check that our indexes are ok 04043 if (FirstIndex < 0 || LastIndex < 0 || LastIndex <= FirstIndex || FirstIndex >= NumElements 04044 || LastIndex > NumElements) 04045 { 04046 ERROR3("Invalid inputs to OpNodePathEditBlob::GetLengthOfEditSection"); 04047 return -1; 04048 } 04049 04050 // get the coordinates 04051 DocCoord* pCoords = pPath->GetCoordArray(); 04052 ERROR2IF(pCoords == NULL, -1, "Failed to get coord array in OpNodePathEditBlob::GetLengthOfEditSection"); 04053 04054 DocCoord FirstCoord = pCoords[FirstIndex]; 04055 DocCoord LastCoord = pCoords[LastIndex]; 04056 04057 // Now get the distances along the path to these points 04058 MILLIPOINT FirstDistance = -1; 04059 MILLIPOINT LastDistance = -1; 04060 04061 BOOL ok = pPath->GetDistanceToPoint(FirstCoord, &FirstDistance); 04062 if (ok) 04063 ok = pPath->GetDistanceToPoint(LastCoord, &LastDistance); 04064 04065 MILLIPOINT SectionLength = -1; 04066 if (ok) 04067 SectionLength = LastDistance - FirstDistance; 04068 04069 return SectionLength; 04070 }
|
|
Find out the state of the operation at the specific time.
Reimplemented in OpNodePathEditControlBlob, OpNodePathAddEndpoint, OpCloseNodePaths, OpReshapeOrAddPoint, and OpNewPath. Definition at line 3351 of file pathedit.cpp. 03352 { 03353 OpState Blobby; 03354 03355 return Blobby; 03356 }
|
|
Adds the operation to the list of all known operations.
Reimplemented from SimpleCCObject. Reimplemented in OpNodePathEditControlBlob, OpNodePathAddEndpoint, OpCloseNodePaths, OpReshapeOrAddPoint, and OpNewPath. Definition at line 3325 of file pathedit.cpp. 03326 { 03327 return (RegisterOpDescriptor( 0, 03328 _R(IDS_NODEPATH_EDIT), 03329 CC_RUNTIME_CLASS(OpNodePathEditBlob), 03330 OPTOKEN_NODEPATH, 03331 OpNodePathEditBlob::GetState, 03332 0, // help ID 03333 _R(IDBBL_NODEPATHOP), 03334 0 ) ); // bitmap ID */ 03335 }
|
|
To adjust the number of steps in a blend on a path as a result of the path being edited (which is why its here rather than in the blend code). First the number of steps is calculated from the new path distance and if different a new action is inserted.
Definition at line 1601 of file pathedit.cpp. 01602 { 01603 ERROR2IF(pNodeBlend==NULL, FALSE, "NodeBlend pointer is NULL"); 01604 // do we wish to keep the distance between steps constant? If so then determine 01605 // how many steps we need with the new length and make an action. 01606 if (pNodeBlend->GetEditState() == EDIT_DISTANCE) 01607 { 01608 UINT32 NewNumSteps = 0; 01609 UINT32 OldNumSteps = pNodeBlend->GetNumBlendSteps(); 01610 double StepDistance = pNodeBlend->GetDistanceEntered(); 01611 double NewPathLength = EditPath.GetPathLength(); 01612 NewNumSteps = (UINT32)(NewPathLength/StepDistance); 01613 BOOL ok = TRUE; 01614 01615 01616 if (OldNumSteps != NewNumSteps) 01617 { 01618 ChangeBlendStepsAction* pAction; 01619 if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,pNodeBlend,TRUE) != AC_FAIL); 01620 if (ok) ok = ChangeBlendStepsAction::Init(this,&UndoActions,pNodeBlend,OldNumSteps,StepDistance,&pAction) != AC_FAIL; 01621 if (ok) ok = DoInvalidateNodeRegion(pNodeBlend,TRUE,FALSE); 01622 if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,pNodeBlend,TRUE) != AC_FAIL); 01623 pNodeBlend->SetNumBlendSteps(NewNumSteps); 01624 } 01625 01626 // added 9/9/99 now we are shifting the last object along the curve to ensure precise 01627 // step distances. To do this we must set the proportion of the curve used in the 01628 // NodeBlender objects. 01629 if (ok) 01630 { 01631 double PathDistanceUsed = NewNumSteps * StepDistance; 01632 double PathProportion = PathDistanceUsed / NewPathLength; 01633 // double PathDistanceUnused = NewPathLength - PathDistanceUsed; 01634 01635 if (PathProportion != 1.0) 01636 { 01637 ChangeBlenderOpParam BlenderParam; 01638 BlenderParam.m_ChangeType = CHANGEBLENDER_PATHEND; 01639 01640 NodeBlender* pNodeBlender = pNodeBlend->FindFirstBlender(); 01641 INT32 NumBlenders = pNodeBlend->GetNumBlenders(); 01642 01643 while (pNodeBlender != NULL) 01644 { 01645 NumBlenders--; 01646 if (NumBlenders ==0) 01647 { 01648 BlenderParam.m_NewPathEnd = PathProportion; 01649 ok = ChangeBlenderAction::Init(this, &UndoActions, pNodeBlender, BlenderParam); 01650 if (ok) 01651 { 01652 DocCoord NewPoint; 01653 double ExtraParam = 0.0; //passed to the function but not used afterwards 01654 ok = pNodeBlender->GetPointOnNodeBlendPath(1.0,&NewPoint,&ExtraParam); 01655 if (ok) 01656 { 01657 NodeRenderableInk* pEnd = pNodeBlender->GetNodeEnd(); 01658 NodeBlend* pNodeBlend = pNodeBlender->GetNodeBlend(); 01659 ok = ((pEnd != NULL) && (pNodeBlend != NULL)); 01660 01661 if (ok) 01662 ok = pNodeBlend->TransformNodeToPoint(pEnd,&NewPoint,this,ExtraParam); 01663 } 01664 } 01665 } 01666 pNodeBlender = pNodeBlend->FindNextBlender(pNodeBlender); 01667 } 01668 } // end if (pathproportion.. 01669 } // end if(ok) 01670 } 01671 return TRUE; 01672 }
|
|
Looks at the member variables dealing with snapping to another path and joins the paths together. It will always join the other path to the original path, keeping the original path's attributes intact. NOTE: This routine will alter the OriginalPath member variable if it joins paths, because it has to make a copy of the path for undo purposes.
Definition at line 1984 of file pathedit.cpp. 01985 { 01986 // If SnapToAnother is false there's no snapping to be done, so just return successfully 01987 if (!SnapToAnother) 01988 return TRUE; 01989 01990 // If we're joining with another path, the rules say we can only have one selected point. 01991 PathFlags* Flags = (*pOrigPath)->InkPath.GetFlagArray(); 01992 INT32 NumCoords = (*pOrigPath)->InkPath.GetNumCoords(); 01993 01994 NodePath* OldSnapPath = SnapToPath; 01995 01996 INT32 MainIndex; 01997 for (MainIndex=0; MainIndex<NumCoords; MainIndex++) 01998 { 01999 if (Flags[MainIndex].IsEndPoint && Flags[MainIndex].IsSelected) 02000 break; 02001 } 02002 02003 // on exit, MainIndex is the selected endpoint, or = NumCoords 02004 02005 ENSURE(MainIndex<NumCoords,"There isn't a selected endpoint in the original path (JoinWithAnotherPath)"); 02006 02007 // We're joining to another path, so the easiest way to handle undo is to make a deep copy 02008 // of the original path, then join that with the othe path, put it back into the tree 02009 // and delete the old one. Simple. 02010 Node* pnp; 02011 (*pOrigPath)->NodeCopy(&pnp); // Make a deep copy of the original path, with attributes 02012 NodePath* MainPath = (NodePath*)pnp; 02013 02014 if (!MainPath) 02015 return FALSE; 02016 02017 // Now that we have a copy of this path, let's join it with the other path 02018 02019 if (SnapToAnother) 02020 { 02021 // If we're snapping to a subpath in the same path, change SnapToPath because we're 02022 // no longer joining to OriginalPath. 02023 if (SnapToPath == (*pOrigPath)) 02024 SnapToPath = MainPath; 02025 02026 // If we're snapping to another, the first thing I have to do is change the control 02027 // point of the point in the other path that we're snapping to, because it might 02028 // have been smoothed. 02029 02030 if (SnapToLineOrCurve) // TRUE if the path has been smoothed 02031 { 02032 PathVerb* OtherVerbs = SnapToPath->InkPath.GetVerbArray(); 02033 PathFlags* OtherFlags = SnapToPath->InkPath.GetFlagArray(); 02034 DocCoord* OtherCoords = SnapToPath->InkPath.GetCoordArray(); 02035 02036 if (OtherVerbs[SnapToIndex] == PT_MOVETO) 02037 { 02038 // Don't need to undo if SnapToPath == MainPath 02039 if (SnapToPath == MainPath) 02040 OtherCoords[SnapToIndex+1] = SnapToCoords[1]; 02041 else 02042 DoAlterPathElement( SnapToPath, 02043 SnapToIndex+1, 02044 SnapToCoords[1], 02045 OtherFlags[SnapToIndex+1], 02046 OtherVerbs[SnapToIndex+1]); 02047 } 02048 else 02049 { 02050 if (SnapToPath == MainPath) 02051 OtherCoords[SnapToIndex-1] = SnapToCoords[1]; 02052 else 02053 DoAlterPathElement( SnapToPath, 02054 SnapToIndex-1, 02055 SnapToCoords[1], 02056 OtherFlags[SnapToIndex-1], 02057 OtherVerbs[SnapToIndex-1]); 02058 } 02059 } 02060 02061 if (!MainPath->InkPath.JoinToAnother(&(SnapToPath->InkPath), MainIndex, SnapToIndex)) 02062 { 02063 MainPath->CascadeDelete(); 02064 delete MainPath; 02065 return FALSE; 02066 } 02067 } 02068 02069 // We've joined successfully, so let's insert this new node into the tree next to the original 02070 if (!DoInsertNewNode(MainPath, (*pOrigPath), NEXT, TRUE, FALSE)) 02071 { 02072 MainPath->CascadeDelete(); 02073 delete MainPath; 02074 return FALSE; 02075 } 02076 02077 // Hide the original path 02078 if (!DoHideNode((*pOrigPath), TRUE)) 02079 return FALSE; 02080 02081 // Hide the node we joined to 02082 if (OldSnapPath != (*pOrigPath)) 02083 { 02084 if (!DoHideNode(OldSnapPath, TRUE)) 02085 return FALSE; 02086 } 02087 02088 // Change the pOrigPath variable so that subsequent operations work properly 02089 (*pOrigPath) = MainPath; 02090 02091 return TRUE; 02092 }
|
|
Looks at the member variables dealing with snapping to another path and joins the paths together. It will always join the other path to the original path, keeping the original path's attributes intact. NOTE: This routine will alter the OriginalPath member variable if it joins paths, because it has to make a copy of the path for undo purposes.
Definition at line 1856 of file pathedit.cpp. 01857 { 01858 // If SnapToAnother is false there's no snapping to be done, so just return successfully 01859 if (!SnapToAnother) 01860 return TRUE; 01861 01862 // If we're joining with another path, the rules say we can only have one selected point. 01863 PathFlags* Flags = OriginalPath->InkPath.GetFlagArray(); 01864 INT32 NumCoords = OriginalPath->InkPath.GetNumCoords(); 01865 01866 NodePath* OldSnapPath = SnapToPath; 01867 01868 INT32 MainIndex; 01869 for (MainIndex=0; MainIndex<NumCoords; MainIndex++) 01870 { 01871 if (Flags[MainIndex].IsEndPoint && Flags[MainIndex].IsSelected) 01872 break; 01873 } 01874 01875 // on exit, MainIndex is the selected endpoint, or = NumCoords 01876 01877 ENSURE(MainIndex<NumCoords,"There isn't a selected endpoint in the original path (JoinWithAnotherPath)"); 01878 01879 // We're joining to another path, so the easiest way to handle undo is to make a deep copy 01880 // of the original path, then join that with the othe path, put it back into the tree 01881 // and delete the old one. Simple. 01882 Node* pnp; 01883 OriginalPath->NodeCopy(&pnp); // Make a deep copy of the original path, with attributes 01884 NodePath* MainPath = (NodePath*)pnp; 01885 01886 if (!MainPath) 01887 return FALSE; 01888 01889 // Now that we have a copy of this path, let's join it with the other path 01890 01891 if (SnapToAnother) 01892 { 01893 // If we're snapping to a subpath in the same path, change SnapToPath because we're 01894 // no longer joining to OriginalPath. 01895 if (SnapToPath == OriginalPath) 01896 SnapToPath = MainPath; 01897 01898 // If we're snapping to another, the first thing I have to do is change the control 01899 // point of the point in the other path that we're snapping to, because it might 01900 // have been smoothed. 01901 01902 if (SnapToLineOrCurve) // TRUE if the path has been smoothed 01903 { 01904 PathVerb* OtherVerbs = SnapToPath->InkPath.GetVerbArray(); 01905 PathFlags* OtherFlags = SnapToPath->InkPath.GetFlagArray(); 01906 DocCoord* OtherCoords = SnapToPath->InkPath.GetCoordArray(); 01907 01908 if (OtherVerbs[SnapToIndex] == PT_MOVETO) 01909 { 01910 // Don't need to undo if SnapToPath == MainPath 01911 if (SnapToPath == MainPath) 01912 OtherCoords[SnapToIndex+1] = SnapToCoords[1]; 01913 else 01914 DoAlterPathElement( SnapToPath, 01915 SnapToIndex+1, 01916 SnapToCoords[1], 01917 OtherFlags[SnapToIndex+1], 01918 OtherVerbs[SnapToIndex+1]); 01919 } 01920 else 01921 { 01922 if (SnapToPath == MainPath) 01923 OtherCoords[SnapToIndex-1] = SnapToCoords[1]; 01924 else 01925 DoAlterPathElement( SnapToPath, 01926 SnapToIndex-1, 01927 SnapToCoords[1], 01928 OtherFlags[SnapToIndex-1], 01929 OtherVerbs[SnapToIndex-1]); 01930 } 01931 } 01932 01933 if (!MainPath->InkPath.JoinToAnother(&(SnapToPath->InkPath), MainIndex, SnapToIndex)) 01934 { 01935 MainPath->CascadeDelete(); 01936 delete MainPath; 01937 return FALSE; 01938 } 01939 } 01940 01941 // We've joined successfully, so let's insert this new node into the tree next to the original 01942 if (!DoInsertNewNode(MainPath, OriginalPath, NEXT, TRUE, FALSE)) 01943 { 01944 MainPath->CascadeDelete(); 01945 delete MainPath; 01946 return FALSE; 01947 } 01948 01949 // Hide the original path 01950 if (!DoHideNode(OriginalPath, TRUE)) 01951 return FALSE; 01952 01953 // Hide the node we joined to 01954 if (OldSnapPath != OriginalPath) 01955 { 01956 if (!DoHideNode(OldSnapPath, TRUE)) 01957 return FALSE; 01958 } 01959 01960 // Change the OriginalPath member variable so that subsequent operations work properly 01961 OriginalPath = MainPath; 01962 01963 return TRUE; 01964 }
|
|
This goes through the path, moves all the selected coords by the offset and then performs some magic to smooth the rest of the path round the changes if it needs it.
Definition at line 2658 of file pathedit.cpp. 02659 { 02660 // Get the array that I need 02661 PathFlags* Flags = EditPath.GetFlagArray(); 02662 DocCoord* Coords = EditPath.GetCoordArray(); 02663 02664 INT32 NumCoords = EditPath.GetNumCoords(); 02665 02666 // Go though all the points 02667 for (INT32 i=0; i<NumCoords; i++) 02668 { 02669 // and translate them by the drag offset if they are selected 02670 if (Flags[i].IsSelected) 02671 Coords[i].translate( Offset.x, Offset.y ); 02672 } 02673 02674 // And now smooth out the new path 02675 EditPath.SmoothCurve(TRUE, SnapEnds, SnapIndex); 02676 02677 // Now to snap (possibly) to another path, if the SnapToAnother flag is set 02678 // This not only entails changing the part of the line we're dragging, but it might 02679 // also mean we have to set the SnapToCoords array to contain a snapped bezier segment 02680 if (SnapToAnother) 02681 { 02682 // Get the array pointers 02683 PathVerb* Verbs = EditPath.GetVerbArray(); 02684 Flags = EditPath.GetFlagArray(); 02685 Coords = EditPath.GetCoordArray(); 02686 PathVerb* OtherVerbs = SnapToPath->InkPath.GetVerbArray(); 02687 PathFlags* OtherFlags = SnapToPath->InkPath.GetFlagArray(); 02688 DocCoord* OtherCoords = SnapToPath->InkPath.GetCoordArray(); 02689 02690 // Because we're snapping, we must be on either the start or the end of a subpath 02691 // And the CloseFigure flag will never be set. 02692 // There are sixteen possibilities - for each line, we could be looking at 02693 // a curve or a line, at the start or end of each subpath. This logic enumerates 02694 // all of the possibilities. It may look tortuous, but it gets them all. 02695 if (Verbs[SnapIndex] == PT_MOVETO) 02696 { 02697 // We're dragging the start of a subpath. See if it's a curve 02698 if (Verbs[SnapIndex+1] == PT_BEZIERTO) 02699 { 02700 // We are dragging a curve at the start of the path. See what we've snapped to 02701 if (OtherVerbs[SnapToIndex] == PT_MOVETO) 02702 { 02703 // Snapping a curve at start to the start of the other one 02704 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO) 02705 { 02706 // Snapping curve at beginning with curve at beginning 02707 // Let's smooth this bezier according to the snapping 02708 if (Flags[SnapIndex+1].IsSmooth) 02709 Coords[SnapIndex+1] = EditPath.SmoothControlPoint( SnapIndex+1, 02710 FALSE, // start end not snapped 02711 TRUE, // Joined to another 02712 TRUE, // Other is a curve 02713 OtherCoords[SnapToIndex+3] 02714 ); 02715 // Note that the other control point is not affected by the snap 02716 // Since the other segment is a curve, we have to set up the SnapToCoords array 02717 // so that the render routine works properly 02718 // Notice that the assignment in the if below is required 02719 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex+1].IsSmooth)) 02720 { 02721 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02722 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex+1, 02723 FALSE, 02724 TRUE, 02725 TRUE, 02726 Coords[SnapIndex+3] 02727 ); 02728 SnapToCoords[2] = OtherCoords[SnapToIndex+2]; 02729 SnapToCoords[3] = OtherCoords[SnapToIndex+3]; 02730 } 02731 } 02732 else 02733 { 02734 // Snapping curve at beginning with line at beginning 02735 if (Flags[SnapIndex+1].IsSmooth) 02736 Coords[SnapIndex+1] = EditPath.SmoothControlPoint( SnapIndex+1, 02737 FALSE, // start end not snapped 02738 TRUE, // Joined to another 02739 FALSE, // Other is a line 02740 OtherCoords[SnapToIndex+1] 02741 ); 02742 // Since we're snapping to a line, we just need to set SnapToLineOrCurve to FALSE 02743 SnapToLineOrCurve = FALSE; 02744 02745 } 02746 } 02747 else 02748 { 02749 // Snapping curve at beginning with the end of the other one 02750 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO) 02751 { 02752 // Snapping curve at beginning with curve at end of other one 02753 // Smooth the editpath bezier if the flag says we can 02754 if (Flags[SnapIndex+1].IsSmooth) 02755 Coords[SnapIndex+1] = EditPath.SmoothControlPoint( SnapIndex+1, 02756 FALSE, 02757 TRUE, 02758 TRUE, 02759 OtherCoords[SnapToIndex-3] 02760 ); 02761 // Now set up SnapToCoords array 02762 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex-1].IsSmooth)) // yes the other path is a curve 02763 { 02764 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02765 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex-1, 02766 FALSE, 02767 TRUE, 02768 TRUE, 02769 Coords[SnapIndex+3] 02770 ); 02771 SnapToCoords[2] = OtherCoords[SnapToIndex-2]; 02772 SnapToCoords[3] = OtherCoords[SnapToIndex-3]; 02773 } 02774 } 02775 else 02776 { 02777 // snapping curve at beginning with line at end of other one 02778 if (Flags[SnapIndex+1].IsSmooth) 02779 Coords[SnapIndex+1] = EditPath.SmoothControlPoint( SnapIndex+1, 02780 FALSE, 02781 TRUE, 02782 FALSE, 02783 OtherCoords[SnapToIndex-1] 02784 ); 02785 // Other is a line, so the SnapToCoords array isn't used 02786 SnapToLineOrCurve = FALSE; 02787 } 02788 } 02789 02790 } 02791 else 02792 { 02793 // Dragging a line at the beginning. What are we snapping to 02794 if (OtherVerbs[SnapToIndex] == PT_MOVETO) 02795 { 02796 // Snapping a line at start to the start of the other one 02797 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO) 02798 { 02799 // Snapping line at beginning with curve at beginning 02800 // There's nothing to smooth in the edit path, but we have to 02801 // set up the SnapToCoords array 02802 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex+1].IsSmooth)) 02803 { 02804 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02805 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex+1, 02806 FALSE, 02807 TRUE, 02808 FALSE, 02809 Coords[SnapIndex+1] 02810 ); 02811 SnapToCoords[2] = OtherCoords[SnapToIndex+2]; 02812 SnapToCoords[3] = OtherCoords[SnapToIndex+3]; 02813 } 02814 } 02815 { 02816 // Snapping line at beginning with line at beginning 02817 // Nothing whatever to smooth, just clear the flag 02818 SnapToLineOrCurve = FALSE; 02819 } 02820 } 02821 else 02822 { 02823 // Snapping line at beginning with the end of the other one 02824 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO) 02825 { 02826 // Snapping line at beginning with curve at end of other one 02827 // Nothing to smooth in editpath, let's set up SnapToCoords array 02828 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex-1].IsSmooth)) 02829 { 02830 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02831 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex-1, 02832 FALSE, 02833 TRUE, 02834 FALSE, 02835 Coords[SnapIndex+1] 02836 ); 02837 SnapToCoords[2] = OtherCoords[SnapToIndex-2]; 02838 SnapToCoords[3] = OtherCoords[SnapToIndex-3]; 02839 } 02840 } 02841 else 02842 { 02843 // snapping line at beginning with line at end of other one 02844 // Just clear the flag 02845 SnapToLineOrCurve = FALSE; 02846 } 02847 } 02848 02849 } 02850 } 02851 else 02852 { 02853 // We're snapping the end of the path, let's see what 02854 if (Verbs[SnapIndex] == PT_BEZIERTO) 02855 { 02856 // Snapping a curve at the end to... what? 02857 if (OtherVerbs[SnapToIndex] == PT_MOVETO) 02858 { 02859 // Snapping a curve at the end to the start of the other one 02860 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO) 02861 { 02862 // Snapping curve at the end with curve at beginning 02863 if (Flags[SnapIndex-1].IsSmooth) 02864 Coords[SnapIndex-1] = EditPath.SmoothControlPoint( SnapIndex-1, 02865 FALSE, 02866 TRUE, 02867 TRUE, 02868 OtherCoords[SnapToIndex+3] 02869 ); 02870 // Set up the SnapToCoords array 02871 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex+1].IsSmooth)) 02872 { 02873 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02874 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex+1, 02875 FALSE, 02876 TRUE, 02877 TRUE, 02878 Coords[SnapIndex-3] 02879 ); 02880 SnapToCoords[2] = OtherCoords[SnapToIndex+2]; 02881 SnapToCoords[3] = OtherCoords[SnapToIndex+3]; 02882 } 02883 } 02884 else 02885 { 02886 // Snapping curve at the end with line at beginning 02887 if (Flags[SnapIndex-1].IsSmooth) 02888 Coords[SnapIndex-1] = EditPath.SmoothControlPoint( SnapIndex-1, 02889 FALSE, 02890 TRUE, 02891 FALSE, 02892 OtherCoords[SnapToIndex+1] 02893 ); 02894 02895 // Clear flag for SnapToCoords array 02896 SnapToLineOrCurve = FALSE; 02897 } 02898 } 02899 else 02900 { 02901 // Snapping curve at the end with the end of the other one 02902 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO) 02903 { 02904 // Snapping curve at the end with curve at end of other one 02905 if (Flags[SnapIndex-1].IsSmooth) 02906 Coords[SnapIndex-1] = EditPath.SmoothControlPoint( SnapIndex-1, 02907 FALSE, 02908 TRUE, 02909 TRUE, 02910 OtherCoords[SnapToIndex-3] 02911 ); 02912 // Init the SnapToCoords array 02913 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex-1].IsSmooth)) 02914 { 02915 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02916 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex-1, 02917 FALSE, 02918 TRUE, 02919 TRUE, 02920 Coords[SnapIndex-3] 02921 ); 02922 SnapToCoords[2] = OtherCoords[SnapToIndex-2]; 02923 SnapToCoords[3] = OtherCoords[SnapToIndex-3]; 02924 } 02925 } 02926 else 02927 { 02928 // snapping curve at the end with line at end of other one 02929 if (Flags[SnapIndex-1].IsSmooth) 02930 Coords[SnapIndex-1] = EditPath.SmoothControlPoint( SnapIndex-1, 02931 FALSE, 02932 TRUE, 02933 FALSE, 02934 OtherCoords[SnapToIndex-1] 02935 ); 02936 // Other is a line so clear the flag 02937 SnapToLineOrCurve = FALSE; 02938 } 02939 } 02940 02941 } 02942 else 02943 { 02944 // Snapping a line at the end with something 02945 if (OtherVerbs[SnapToIndex] == PT_MOVETO) 02946 { 02947 // Snapping a line at the end to the start of the other one 02948 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO) 02949 { 02950 // Snapping line at the end with curve at beginning 02951 // Nothing to smooth in the edit path, but we should set up SnapToCoords array 02952 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex+1].IsSmooth)) 02953 { 02954 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02955 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex+1, 02956 FALSE, 02957 TRUE, 02958 FALSE, 02959 Coords[SnapIndex-1] 02960 ); 02961 SnapToCoords[2] = OtherCoords[SnapToIndex+2]; 02962 SnapToCoords[3] = OtherCoords[SnapToIndex+3]; 02963 } 02964 } 02965 { 02966 // Snapping line at the end with line at beginning 02967 // Just clear the flag 02968 SnapToLineOrCurve = FALSE; 02969 } 02970 } 02971 else 02972 { 02973 // Snapping line at the end with the end of the other one 02974 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO) 02975 { 02976 // Snapping line at the end with curve at end of other one 02977 // Nothing to smooth in Editpath, but we have to do the array 02978 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex-1].IsSmooth)) 02979 { 02980 SnapToCoords[0] = OtherCoords[SnapToIndex]; 02981 SnapToCoords[1] = SnapToPath->InkPath.SmoothControlPoint( SnapToIndex-1, 02982 FALSE, 02983 TRUE, 02984 FALSE, 02985 Coords[SnapIndex-1] 02986 ); 02987 SnapToCoords[2] = OtherCoords[SnapToIndex-2]; 02988 SnapToCoords[3] = OtherCoords[SnapToIndex-3]; 02989 } 02990 } 02991 else 02992 { 02993 // snapping line at the end with line at end of other one 02994 // Just clear the flag 02995 SnapToLineOrCurve = FALSE; 02996 } 02997 } 02998 02999 } 03000 } 03001 03002 } 03003 03004 }
|
|
This goes through the path, moves all the selected coords by the offset and then performs some magic to smooth the rest of the path round the changes if it needs it.
Definition at line 3027 of file pathedit.cpp. 03028 { 03029 //NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead (); 03030 //NodeListItem* pCurrentEdit = (NodeListItem*) EditPaths.GetHead (); 03031 03032 //while (/*(pCurrentOrig) &&*/ (pCurrentEdit)) 03033 //{ 03034 //NodePath* pOrigPath = (NodePath*) (pCurrentOrig->pNode); 03035 // Path* pEditPath = (Path*) (pCurrentEdit->pNode); 03036 03037 // Get the array that I need 03038 PathFlags* Flags = pEditPath->GetFlagArray(); 03039 DocCoord* Coords = pEditPath->GetCoordArray(); 03040 03041 INT32 NumCoords = pEditPath->GetNumCoords(); 03042 03043 // Go though all the points 03044 for (INT32 i=0; i<NumCoords; i++) 03045 { 03046 // and translate them by the drag offset if they are selected 03047 if (Flags[i].IsSelected) 03048 Coords[i].translate( Offset.x, Offset.y ); 03049 } 03050 03051 // And now smooth out the new path 03052 pEditPath->SmoothCurve(TRUE, SnapEnds, SnapIndex); 03053 03054 //pCurrentOrig = (NodeListItem*) OriginalPaths.GetNext (pCurrentOrig); 03055 // pCurrentEdit = (NodeListItem*) EditPaths.GetNext (pCurrentEdit); 03056 //} 03057 }
|
|
Renders the new version of the path to the window. It makes use of flags in the path to determine which segments of the path need to be rendered.
Reimplemented from Operation. Reimplemented in OpNodePathEditControlBlob. Definition at line 3069 of file pathedit.cpp. 03070 { 03071 RenderPathEditBlobs(Rect,pSpread); 03072 if (EditObjChange.ChangeMask.EorBlobs) 03073 EditObjChange.RenderCurrentBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE); 03074 }
|
|
Call this function to render all the blobs on screen from this operation.
Definition at line 3100 of file pathedit.cpp. 03101 { 03102 RenderPathEditBlobs(pEditPath, pSpread); 03103 }
|
|
Call this function to render all the blobs on screen from this operation.
Reimplemented in OpNodePathEditControlBlob. Definition at line 3085 of file pathedit.cpp. 03086 { 03087 RenderPathEditBlobs(Rect, pSpread); 03088 }
|
|
Call this function to render all the blobs on screen from this operation.
Definition at line 3213 of file pathedit.cpp. 03214 { 03215 // First we have to build a path to render 03216 Path RenderPath; 03217 if ( RenderPath.Initialise(24, 12) == FALSE ) 03218 { 03219 // We did not get the memory, so don't draw anything 03220 return; 03221 } 03222 03223 DocRect Rect = pEditPath->GetBoundingRect(); 03224 03225 BOOL IsInCurve = FALSE; 03226 INT32 NumCoords = pEditPath->GetNumCoords(); 03227 for (INT32 i=0; i<NumCoords; i++) 03228 { 03229 // Dereference the pointers I need 03230 PathFlags* Flags = pEditPath->GetFlagArray(); 03231 DocCoord* Coords = pEditPath->GetCoordArray(); 03232 PathVerb* Verbs = pEditPath->GetVerbArray(); 03233 03234 // We only consider the end points 03235 if (Flags[i].IsEndPoint) 03236 { 03237 if (IsInCurve) 03238 { 03239 // we are already adding to the curve, so see if we should continue adding 03240 if (Flags[i].NeedToRender) 03241 { 03242 switch (Verbs[i] & (~PT_CLOSEFIGURE)) 03243 { 03244 case PT_MOVETO: 03245 RenderPath.InsertMoveTo(Coords[i]); 03246 break; 03247 03248 case PT_LINETO: 03249 RenderPath.InsertLineTo(Coords[i]); 03250 break; 03251 03252 case PT_BEZIERTO: 03253 RenderPath.InsertCurveTo(Coords[i-2], Coords[i-1], Coords[i]); 03254 break; 03255 03256 default: 03257 break; 03258 } 03259 } 03260 else 03261 { 03262 IsInCurve = FALSE; 03263 } 03264 } 03265 else 03266 { 03267 // We are not currently adding to the render path, so start 03268 if (Flags[i].NeedToRender) 03269 { 03270 switch (Verbs[i] & (~PT_CLOSEFIGURE)) 03271 { 03272 case PT_MOVETO: 03273 RenderPath.InsertMoveTo(Coords[i]); 03274 break; 03275 case PT_BEZIERTO: 03276 RenderPath.InsertMoveTo(Coords[i-3]); 03277 RenderPath.InsertCurveTo(Coords[i-2],Coords[i-1],Coords[i]); 03278 break; 03279 case PT_LINETO: 03280 RenderPath.InsertMoveTo(Coords[i-1]); 03281 RenderPath.InsertLineTo(Coords[i]); 03282 break; 03283 } 03284 IsInCurve = TRUE; 03285 } 03286 } 03287 } 03288 } 03289 03290 // And if we've snapped to another curve 03291 if (SnapToLineOrCurve) 03292 { 03293 // We are snapping to another curve, so render the curve 03294 RenderPath.InsertMoveTo(SnapToCoords[0]); 03295 RenderPath.InsertCurveTo(SnapToCoords[1],SnapToCoords[2],SnapToCoords[3]); 03296 } 03297 03298 // Make sure that there is something to draw 03299 if (RenderPath.GetNumCoords()==0) 03300 return; 03301 03302 // And this bit actually draws the path we have just made 03303 RenderRegion* pRegion = DocView::RenderOnTop( NULL, StartSpread, ClippedEOR ); 03304 while (pRegion != NULL) 03305 { 03306 pRegion->SetLineColour( COLOUR_XORNEW ); // Set the line colour 03307 pRegion->DrawPath( &RenderPath ); // Draw an EORed version of how the path will turn out 03308 pRegion = DocView::GetNextOnTop( &Rect ); // Get the next render region 03309 } 03310 }
|
|
Definition at line 3106 of file pathedit.cpp. 03107 { 03108 // First we have to build a path to render 03109 Path RenderPath; 03110 if ( RenderPath.Initialise(24, 12) == FALSE ) 03111 { 03112 // We did not get the memory, so don't draw anything 03113 return; 03114 } 03115 03116 BOOL IsInCurve = FALSE; 03117 INT32 NumCoords = EditPath.GetNumCoords(); 03118 for (INT32 i=0; i<NumCoords; i++) 03119 { 03120 // Dereference the pointers I need 03121 PathFlags* Flags = EditPath.GetFlagArray(); 03122 DocCoord* Coords = EditPath.GetCoordArray(); 03123 PathVerb* Verbs = EditPath.GetVerbArray(); 03124 03125 // We only consider the end points 03126 if (Flags[i].IsEndPoint) 03127 { 03128 if (IsInCurve) 03129 { 03130 // we are already adding to the curve, so see if we should continue adding 03131 if (Flags[i].NeedToRender) 03132 { 03133 switch (Verbs[i] & (~PT_CLOSEFIGURE)) 03134 { 03135 case PT_MOVETO: 03136 RenderPath.InsertMoveTo(Coords[i]); 03137 break; 03138 03139 case PT_LINETO: 03140 RenderPath.InsertLineTo(Coords[i]); 03141 break; 03142 03143 case PT_BEZIERTO: 03144 RenderPath.InsertCurveTo(Coords[i-2], Coords[i-1], Coords[i]); 03145 break; 03146 03147 default: 03148 break; 03149 } 03150 } 03151 else 03152 { 03153 IsInCurve = FALSE; 03154 } 03155 } 03156 else 03157 { 03158 // We are not currently adding to the render path, so start 03159 if (Flags[i].NeedToRender) 03160 { 03161 switch (Verbs[i] & (~PT_CLOSEFIGURE)) 03162 { 03163 case PT_MOVETO: 03164 RenderPath.InsertMoveTo(Coords[i]); 03165 break; 03166 case PT_BEZIERTO: 03167 RenderPath.InsertMoveTo(Coords[i-3]); 03168 RenderPath.InsertCurveTo(Coords[i-2],Coords[i-1],Coords[i]); 03169 break; 03170 case PT_LINETO: 03171 RenderPath.InsertMoveTo(Coords[i-1]); 03172 RenderPath.InsertLineTo(Coords[i]); 03173 break; 03174 } 03175 IsInCurve = TRUE; 03176 } 03177 } 03178 } 03179 } 03180 03181 // And if we've snapped to another curve 03182 if (SnapToLineOrCurve) 03183 { 03184 // We are snapping to another curve, so render the curve 03185 RenderPath.InsertMoveTo(SnapToCoords[0]); 03186 RenderPath.InsertCurveTo(SnapToCoords[1],SnapToCoords[2],SnapToCoords[3]); 03187 } 03188 03189 // Make sure that there is something to draw 03190 if (RenderPath.GetNumCoords()==0) 03191 return; 03192 03193 // And this bit actually draws the path we have just made 03194 RenderRegion* pRegion = DocView::RenderOnTop( NULL, StartSpread, ClippedEOR ); 03195 while (pRegion != NULL) 03196 { 03197 pRegion->SetLineColour( COLOUR_XORNEW ); // Set the line colour 03198 pRegion->DrawPath( &RenderPath ); // Draw an EORed version of how the path will turn out 03199 pRegion = DocView::GetNextOnTop( &Rect ); // Get the next render region 03200 } 03201 }
|
|
Updates the status line message to reflect the current situation.
Reimplemented in OpNodePathEditControlBlob, OpNodePathAddEndpoint, and OpReshapeOrAddPoint. Definition at line 3367 of file pathedit.cpp. 03368 { 03369 String_256 HelpString; 03370 if (EndSnapped) 03371 HelpString = String_256(_R(IDS_PATHDRAGCREATESHAPE)); 03372 else 03373 { 03374 if (SnapToAnother) 03375 HelpString = String_256(_R(IDS_PATHDRAGJOINPATHS)); 03376 else 03377 HelpString = String_256(_R(IDS_PATHDRAGFINISH)); 03378 } 03379 GetApplication()->UpdateStatusBarText(&HelpString, FALSE); 03380 }
|
|
Sets the closefigure flag in the last element in the subpath. Also turns off the rotate bit in the points we're snapping together if their smoothing bits are also turned off. This prevents us creating a cusp that has rotate flags set.
Definition at line 1775 of file pathedit.cpp. 01776 { 01777 // If ends are snapping, there can only be one selected point on the path... 01778 // Get a pointer to the path's verbs 01779 PathVerb* Verbs = pEditPath->GetVerbArray(); 01780 PathFlags* Flags = pEditPath->GetFlagArray(); 01781 INT32 NumCoords = pEditPath->GetNumCoords(); 01782 01783 // Find the selected point 01784 INT32 pos; 01785 for ( pos = 0;pos<NumCoords && !(Flags[pos].IsEndPoint && Flags[pos].IsSelected);pos++); 01786 01787 // Now pos is the index of the selected point 01788 01789 // This next may seem like a lot of faffing around, but we don't know whether the 01790 // selected point is the start or the end of the path, so this code doesn't care 01791 // (thus it's not very optimal, but it shouldn't matter). 01792 01793 // Move to the start of the edit path 01794 INT32 startpos = pos; 01795 pEditPath->FindStartOfSubPath(&startpos); 01796 // find the end element (might be a curve or a line) 01797 pos=startpos; 01798 pEditPath->FindEndOfSubPath(&pos); 01799 01800 // if the last element is a bezier, pos points at the first control point 01801 // so we have to add 2 to move to the endpoint of the curve 01802 if (Verbs[pos] == PT_BEZIERTO) 01803 pos+=2; 01804 01805 // Now simply set the PT_CLOSEFIGURE flag in this verb 01806 Verbs[pos] |= PT_CLOSEFIGURE; 01807 01808 // make sure the first and last points are selected, along with adjacent ctrl points 01809 Flags[pos].IsSelected = TRUE; 01810 // if it's a bezier, select previous control point and check state of smooth/rotate bits 01811 if ((Verbs[pos] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) 01812 { 01813 Flags[pos-1].IsSelected = TRUE; 01814 01815 // if the smooth flag is not set, clear the rotate flag as well, otherwise 01816 // We'll have something that looks like a cusp, but as soon as you drag a control 01817 // point, the opposite point will rotate around. 01818 if (!Flags[pos-1].IsSmooth) 01819 Flags[pos-1].IsRotate = FALSE; 01820 01821 // Do the same for the endpoint... 01822 if (!Flags[pos].IsSmooth) 01823 Flags[pos].IsRotate = FALSE; 01824 } 01825 pos = startpos; 01826 Flags[pos].IsSelected = TRUE; 01827 if (Verbs[pos+1] == PT_BEZIERTO) 01828 { 01829 Flags[pos+1].IsSelected = TRUE; 01830 01831 // As above, clear the rotate bit if the smooth bit is clear 01832 if (!Flags[pos+1].IsSmooth) 01833 Flags[pos+1].IsRotate = FALSE; 01834 // Do the same for the endpoint... 01835 if (!Flags[pos].IsSmooth) 01836 Flags[pos].IsRotate = FALSE; 01837 } 01838 }
|
|
Sets the closefigure flag in the last element in the subpath. Also turns off the rotate bit in the points we're snapping together if their smoothing bits are also turned off. This prevents us creating a cusp that has rotate flags set.
Definition at line 1692 of file pathedit.cpp. 01693 { 01694 // If ends are snapping, there can only be one selected point on the path... 01695 // Get a pointer to the path's verbs 01696 PathVerb* Verbs = EditPath.GetVerbArray(); 01697 PathFlags* Flags = EditPath.GetFlagArray(); 01698 INT32 NumCoords = EditPath.GetNumCoords(); 01699 01700 // Find the selected point 01701 INT32 pos; 01702 for( pos = 0; pos < NumCoords && !( Flags[pos].IsEndPoint && Flags[pos].IsSelected); pos++ ); 01703 01704 // Now pos is the index of the selected point 01705 01706 // This next may seem like a lot of faffing around, but we don't know whether the 01707 // selected point is the start or the end of the path, so this code doesn't care 01708 // (thus it's not very optimal, but it shouldn't matter). 01709 01710 // Move to the start of the edit path 01711 INT32 startpos = pos; 01712 EditPath.FindStartOfSubPath(&startpos); 01713 // find the end element (might be a curve or a line) 01714 pos=startpos; 01715 EditPath.FindEndOfSubPath(&pos); 01716 01717 // if the last element is a bezier, pos points at the first control point 01718 // so we have to add 2 to move to the endpoint of the curve 01719 if (Verbs[pos] == PT_BEZIERTO) 01720 pos+=2; 01721 01722 // Now simply set the PT_CLOSEFIGURE flag in this verb 01723 Verbs[pos] |= PT_CLOSEFIGURE; 01724 01725 // make sure the first and last points are selected, along with adjacent ctrl points 01726 Flags[pos].IsSelected = TRUE; 01727 // if it's a bezier, select previous control point and check state of smooth/rotate bits 01728 if ((Verbs[pos] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) 01729 { 01730 Flags[pos-1].IsSelected = TRUE; 01731 01732 // if the smooth flag is not set, clear the rotate flag as well, otherwise 01733 // We'll have something that looks like a cusp, but as soon as you drag a control 01734 // point, the opposite point will rotate around. 01735 if (!Flags[pos-1].IsSmooth) 01736 Flags[pos-1].IsRotate = FALSE; 01737 01738 // Do the same for the endpoint... 01739 if (!Flags[pos].IsSmooth) 01740 Flags[pos].IsRotate = FALSE; 01741 } 01742 pos = startpos; 01743 Flags[pos].IsSelected = TRUE; 01744 if (Verbs[pos+1] == PT_BEZIERTO) 01745 { 01746 Flags[pos+1].IsSelected = TRUE; 01747 01748 // As above, clear the rotate bit if the smooth bit is clear 01749 if (!Flags[pos+1].IsSmooth) 01750 Flags[pos+1].IsRotate = FALSE; 01751 // Do the same for the endpoint... 01752 if (!Flags[pos].IsSmooth) 01753 Flags[pos].IsRotate = FALSE; 01754 } 01755 }
|
|
Definition at line 205 of file pathedit.h. |
|
Definition at line 203 of file pathedit.h. |
|
Definition at line 204 of file pathedit.h. |
|
Definition at line 232 of file pathedit.h. |
|
Definition at line 241 of file pathedit.h. |
|
Definition at line 244 of file pathedit.h. |
|
Definition at line 237 of file pathedit.h. |
|
Definition at line 209 of file pathedit.h. |
|
Definition at line 213 of file pathedit.h. |
|
Definition at line 221 of file pathedit.h. |
|
Definition at line 202 of file pathedit.h. |
|
Definition at line 216 of file pathedit.h. |
|
Definition at line 231 of file pathedit.h. |
|
Definition at line 239 of file pathedit.h. |
|
Definition at line 208 of file pathedit.h. |
|
Definition at line 212 of file pathedit.h. |
|
Definition at line 214 of file pathedit.h. |
|
Definition at line 229 of file pathedit.h. |
|
Definition at line 230 of file pathedit.h. |
|
Definition at line 228 of file pathedit.h. |
|
Definition at line 222 of file pathedit.h. |
|
Definition at line 226 of file pathedit.h. |
|
Definition at line 224 of file pathedit.h. |
|
Definition at line 225 of file pathedit.h. |
|
Definition at line 223 of file pathedit.h. |
|
Definition at line 201 of file pathedit.h. |
|
Definition at line 200 of file pathedit.h. |
|
Definition at line 242 of file pathedit.h. |