00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #include "camtypes.h"
00104 #include "pathedit.h"
00105
00106
00107
00108
00109 #include "blobs.h"
00110 #include "csrstack.h"
00111
00112
00113
00114
00115
00116 #include "lineattr.h"
00117 #include "nodepath.h"
00118 #include "ndtxtpth.h"
00119
00120 #include "objchge.h"
00121 #include "pathops.h"
00122 #include "progress.h"
00123
00124
00125 #include "attrmap.h"
00126
00127
00128 #include "ndbldpth.h"
00129 #include "nodeblnd.h"
00130
00131 #include "nodebldr.h"
00132 #include "opdrbrsh.h"
00133
00134 #include "helpids.h"
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 #include "brshattr.h"
00145 #include "opbevel.h"
00146 #include "nodemold.h"
00147 #include "ndmldpth.h"
00148 #include "samplist.h"
00149 #include "brshattr.h"
00150 #include "ophist.h"
00151 #include "blndtool.h"
00152
00153 #define PATRACE if(IsUserName("Peter")) TRACE
00154
00155
00156
00157
00158
00159 #define PACLASSNAME(a,b) CCRuntimeClass* Blob; Blob = a->GetRuntimeClass(); PATRACE(b,Blob->m_lpszClassName)
00160
00161
00162 CC_IMPLEMENT_DYNCREATE( OpJoinShapes, SelOperation)
00163 CC_IMPLEMENT_DYNCREATE( OpBreakShapes, SelOperation)
00164 CC_IMPLEMENT_DYNCREATE( OpDeletePoints, SelOperation)
00165 CC_IMPLEMENT_DYNCREATE( OpNodePathEditBlob, SelOperation)
00166 CC_IMPLEMENT_DYNCREATE( OpToggleSmooth, SelOperation)
00167 CC_IMPLEMENT_DYNCREATE( OpNodePathEditControlBlob, OpNodePathEditBlob)
00168 CC_IMPLEMENT_DYNCREATE( OpReshapeOrAddPoint, OpNodePathEditBlob)
00169 CC_IMPLEMENT_DYNCREATE( OpNodePathAddEndpoint, OpNodePathEditBlob)
00170 CC_IMPLEMENT_DYNCREATE( OpNewPath, OpNodePathEditBlob)
00171 CC_IMPLEMENT_DYNCREATE( OpCloseNodePaths, OpNodePathAddEndpoint)
00172
00173
00174 CC_IMPLEMENT_DYNCREATE( ModifyPathAction, Action)
00175 CC_IMPLEMENT_DYNCREATE( RemovePathElementAction, Action)
00176 CC_IMPLEMENT_DYNCREATE( InsertPathElementAction, Action)
00177 CC_IMPLEMENT_DYNCREATE( ModifyElementAction, Action)
00178 CC_IMPLEMENT_DYNCREATE( ModifyFlagsAction, Action)
00179 CC_IMPLEMENT_DYNCREATE( RecalcBoundsAction, Action)
00180 CC_IMPLEMENT_DYNCREATE( RecordBoundsAction, Action)
00181 CC_IMPLEMENT_DYNCREATE( ModifyFilledAction, Action)
00182 CC_IMPLEMENT_DYNCREATE( SavePathArraysAction, Action)
00183
00184
00185
00186 #define new CAM_DEBUG_NEW
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 OpNodePathEditBlob::OpNodePathEditBlob()
00199 {
00200 EndSnapped = FALSE;
00201 SnapToAnother = FALSE;
00202 pMoveCursor = NULL;
00203 SnapToPath = NULL;
00204 DragStarted = FALSE;
00205 SnapToLineOrCurve = FALSE;
00206 DragPoint = -1;
00207 UpdatePoint = -1;
00208 ConstrainPoint = DocCoord(-1,-1);
00209 ConstrainPrevPoint = DocCoord(-1,-1);
00210 ConstrainNextPoint = DocCoord(-1,-1);
00211 MultiplePaths = FALSE;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 void OpNodePathEditBlob::DoStartDragEdit(NodePath* OrigPath, DocCoord Anchor, Spread *pSpread)
00228 {
00229 BOOL Success = TRUE;
00230
00231
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
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
00267 BevelTools::BuildListOfSelectedNodes(&OriginalPaths, CC_RUNTIME_CLASS(NodeMouldPath));
00268
00269
00270
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)
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
00300 {
00301 MultiplePaths = FALSE;
00302
00303 OriginalPath = OrigPath;
00304
00305
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
00318
00319
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
00334
00335
00336 }
00337
00338
00339 if (DragPoint != -1)
00340 {
00341 ConstrainPoint = OriginalPath->InkPath.GetCoordArray()[DragPoint];
00342
00343
00344 INT32 OtherEndpoint = DragPoint;
00345 if (OriginalPath->InkPath.FindPrevEndPoint(&OtherEndpoint))
00346 ConstrainPrevPoint = OriginalPath->InkPath.GetCoordArray()[OtherEndpoint];
00347 else
00348 ConstrainPrevPoint = ConstrainPoint;
00349
00350
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
00365 Success = BuildEditPath();
00366
00367
00368
00369 if (Success)
00370 Success = (EditObjChange.ObjChangeStarting(OrigPath,this,&EditPath,StartSpread,TRUE) == CC_OK);
00371
00372
00373 if (Success)
00374 Success = CreateCursors();
00375 if (Success)
00376 ChangeCursor(pCrossHairCursor);
00377
00378
00379 DocRect EditPathBBox = EditPath.GetBoundingRect();
00380
00381
00382
00383
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
00397
00398
00399 MultiplePaths = TRUE;
00400
00401 OriginalPath = OrigPath;
00402
00403
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
00426 if (Success)
00427 {
00428 NodeListItem* pCurrentOrig = (NodeListItem*) OriginalPaths.GetHead ();
00429
00430
00431
00432
00433
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
00447
00448
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
00464 }
00465
00466
00467
00468 }
00469
00470
00471
00472
00473
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
00482 INT32 OtherEndpoint = DragPoint;
00483 if (pOrigPath->InkPath.FindPrevEndPoint(&OtherEndpoint))
00484 ConstrainPrevPoint = pOrigPath->InkPath.GetCoordArray()[OtherEndpoint];
00485 else
00486 ConstrainPrevPoint = ConstrainPoint;
00487
00488
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
00503 Success = BuildEditPaths();
00504
00505
00506
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
00554
00555 }
00556 }
00557
00558
00559 if (Success)
00560 Success = CreateCursors();
00561 if (Success)
00562 ChangeCursor(pCrossHairCursor);
00563
00564
00565 DocRect EditPathBBox;
00566
00567 SelRange* Selected = GetApplication()->FindSelection();
00568
00569 EditPathBBox = Selected->GetBlobBoundingRect ();
00570
00571
00572
00573
00574
00575 if (Success)
00576 Success = StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos);
00577
00578 if (!Success)
00579 {
00580 InformError();
00581 FailAndExecute();
00582 End();
00583 }
00584 }
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 void OpNodePathEditBlob::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, Spread *pSpread, BOOL bSolidDrag)
00603 {
00604 if (!MultiplePaths)
00605 {
00606
00607
00608 if (pSpread != StartSpread)
00609 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
00610
00611 Path TempPath;
00612
00613
00614 if (EditObjChange.ChangeMask.EorBlobs)
00615 {
00616 ChangeCode Chge = EditObjChange.RenderCurrentBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE);
00617 if (Chge!=CC_OK)
00618 return;
00619
00620 if (!TempPath.Initialise(EditPath.GetNumCoords(), 12))
00621 return;
00622 TempPath.CopyPathDataFrom(&EditPath);
00623 }
00624
00625
00626 if (DragStarted)
00627 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
00628 else
00629 DragStarted = TRUE;
00630
00631
00632
00633
00634
00635 EndSnapped = FALSE;
00636 SnapToAnother = FALSE;
00637 SnapToLineOrCurve = FALSE;
00638
00639
00640
00641
00642
00643 DocRect PointerBlobRect;
00644 GetApplication()->GetBlobManager()->GetBlobRect(PointerPos,&PointerBlobRect);
00645
00646 DocCoord* Coords = EditPath.GetCoordArray();
00647
00648 PathVerb* Verbs = EditPath.GetVerbArray();
00649 INT32 NumCoords = EditPath.GetNumCoords();
00650
00651 INT32 i;
00652 if (DragPoint != -1)
00653 {
00654
00655 if (Verbs[DragPoint] == PT_MOVETO)
00656 {
00657
00658 i = DragPoint;
00659 if (!EditPath.IsSubPathClosed(i))
00660 {
00661 INT32 NextEndpoint = i;
00662 if (EditPath.FindNextEndPoint(&NextEndpoint))
00663 {
00664 EditPath.FindEndElOfSubPath(&i);
00665
00666
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
00679 i = DragPoint;
00680 if (!EditPath.IsSubPathClosed(i))
00681 {
00682 INT32 PrevEndpoint = i;
00683 if (EditPath.FindPrevEndPoint(&PrevEndpoint))
00684 {
00685 EditPath.FindStartOfSubPath(&i);
00686
00687
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
00700
00701 if (!EndSnapped && DragPoint != -1 && (Verbs[DragPoint] == PT_MOVETO || DragPoint+1 == NumCoords || Verbs[DragPoint+1] == PT_MOVETO) )
00702 {
00703
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 )
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);
00721 if (ThisPath->GetSubPathEnds(&tempStart, &tempEnd))
00722 {
00723 SubEnd = ThisPath->GetPathPosition();
00724
00725
00726 if (ThisPath->GetVerb() == PT_BEZIERTO)
00727 SubEnd+=2;
00728
00729 BOOL ClosedPath = (ThisPath->GetVerbArray()[SubEnd] & PT_CLOSEFIGURE) ;
00730
00731
00732
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;
00753
00754 }
00755
00756
00757 if (SubIndex < ThisNum)
00758 break;
00759 }
00760 pNode = Selected->FindNext(pNode);
00761 }
00762
00763
00764
00765 if (pNode)
00766 {
00767
00768 if (((NodePath*)pNode == OriginalPath) && (OriginalPath->InkPath.GetNumCoords() != EditPath.GetNumCoords()))
00769 {
00770
00771
00772
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
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
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
00813 if (!EndSnapped)
00814 DocView::SnapCurrent(StartSpread,&PointerPos);
00815
00816
00817
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
00830 EditPath.CopyPathDataFrom(&TempPath);
00831 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
00832 return;
00833 }
00834 }
00835
00836
00837 LastMousePos = PointerPos;
00838
00839
00840 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
00841
00842
00843
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
00868
00869 if (pSpread != StartSpread)
00870 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
00871
00872 Path TempPath;
00873
00874
00875 if (pObjChange->ChangeMask.EorBlobs)
00876 {
00877 ChangeCode Chge = pObjChange->RenderCurrentBlobs(pOrigPath,this,pEditPath,StartSpread,TRUE);
00878 if (Chge!=CC_OK)
00879 return;
00880
00881 if (!TempPath.Initialise(pEditPath->GetNumCoords(), 12))
00882 return;
00883 TempPath.CopyPathDataFrom(pEditPath);
00884 }
00885
00886
00887 if (*pDragStarted == TRUE)
00888 {
00889 RenderPathEditBlobs(pEditPath, StartSpread );
00890 }
00891 else
00892 {
00893 *pDragStarted = TRUE;
00894
00895 }
00896
00897 DocRect PointerBlobRect;
00898 GetApplication()->GetBlobManager()->GetBlobRect(PointerPos,&PointerBlobRect);
00899
00900 DocCoord* Coords = pEditPath->GetCoordArray();
00901
00902 PathVerb* Verbs = pEditPath->GetVerbArray();
00903 INT32 NumCoords = pEditPath->GetNumCoords();
00904
00905 if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ())
00906 {
00907
00908
00909
00910
00911
00912
00913
00914
00915 EndSnapped = FALSE;
00916 SnapToAnother = FALSE;
00917 SnapToLineOrCurve = FALSE;
00918
00919
00920
00921
00922
00923 INT32 i;
00924 if (DragPoint != -1)
00925 {
00926
00927 if (Verbs[DragPoint] == PT_MOVETO)
00928 {
00929
00930 i = DragPoint;
00931 if (!pEditPath->IsSubPathClosed(i))
00932 {
00933 INT32 NextEndpoint = i;
00934 if (pEditPath->FindNextEndPoint(&NextEndpoint))
00935 {
00936 pEditPath->FindEndElOfSubPath(&i);
00937
00938
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
00951 i = DragPoint;
00952 if (!pEditPath->IsSubPathClosed(i))
00953 {
00954 INT32 PrevEndpoint = i;
00955 if (pEditPath->FindPrevEndPoint(&PrevEndpoint))
00956 {
00957 pEditPath->FindStartOfSubPath(&i);
00958
00959
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
00972
00973 if (!EndSnapped && DragPoint != -1 && (Verbs[DragPoint] == PT_MOVETO || DragPoint+1 == NumCoords || Verbs[DragPoint+1] == PT_MOVETO) )
00974 {
00975
00976 SelRange* Selected = GetApplication()->FindSelection();
00977
00978
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 )
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);
00998 if (ThisPath->GetSubPathEnds(&tempStart, &tempEnd))
00999 {
01000 SubEnd = ThisPath->GetPathPosition();
01001
01002
01003 if (ThisPath->GetVerb() == PT_BEZIERTO)
01004 SubEnd+=2;
01005
01006 BOOL ClosedPath = (ThisPath->GetVerbArray()[SubEnd] & PT_CLOSEFIGURE) ;
01007
01008
01009
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;
01030
01031 }
01032
01033
01034 if (SubIndex < ThisNum)
01035 break;
01036 }
01037 pNode = Selected->FindNext(pNode);
01038 }
01039
01040
01041
01042 if (pNode)
01043 {
01044
01045 if (((NodePath*)pNode == pOrigPath) && (pOrigPath->InkPath.GetNumCoords() != pEditPath->GetNumCoords()))
01046 {
01047
01048
01049
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
01066
01067
01068
01069
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
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
01097 if (!EndSnapped)
01098 DocView::SnapCurrent(StartSpread,&PointerPos);
01099 }
01100
01101
01102
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
01111
01112
01113
01114
01115 RecalculatePaths (pEditPath, Offset, FALSE , -1 );
01116
01117 if (pObjChange->ChangeMask.EorBlobs)
01118 {
01119 ChangeCode Chge = pObjChange->RenderChangedBlobs(pOrigPath,this,pEditPath,StartSpread,TRUE);
01120 if (Chge!=CC_OK)
01121 {
01122
01123 pEditPath->CopyPathDataFrom(&TempPath);
01124 RenderPathEditBlobs( pEditPath, StartSpread );
01125 return;
01126 }
01127 }
01128
01129
01130 LastMousePos = PointerPos;
01131
01132
01133 RenderPathEditBlobs( pEditPath, StartSpread );
01134
01135
01136
01137
01138
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 }
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169 void OpNodePathEditBlob::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods,
01170 Spread* pSpread, BOOL Success, BOOL bSolidDrag)
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
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
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
01207 GetApplication()->FindSelection()->Update();
01208
01209
01210 FailAndExecute();
01211 End();
01212 return;
01213 }
01214 }
01215 else
01216 {
01217 NotFailed = DoStartSelOp(TRUE,TRUE);
01218
01219
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
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 BOOL OptimiseRedraw = CopyNeedToRenderFlags() && !(EndSnapped || SnapToAnother);
01239 if (!IS_A(OriginalPath,NodePath))
01240 OptimiseRedraw = FALSE;
01241
01242
01243 if (pAttrBrush != NULL)
01244 OptimiseRedraw = FALSE;
01245
01246
01247 if (NotFailed)
01248 NotFailed = RecalcBoundsAction::DoRecalc(this, &UndoActions, OriginalPath, OptimiseRedraw) != AC_FAIL;
01249
01250
01251
01252 if (pAttrBrush != NULL && pAttrBrush->IsTimeStamping() && NotFailed)
01253 {
01254 UpdateBrushAction* pAction;
01255 NotFailed = (UpdateBrushAction::Init(this, &UndoActions, OriginalPath, &pAction) != AC_FAIL);
01256 }
01257
01258
01259 if (NotFailed && EndSnapped)
01260 SnapEndsTogether();
01261
01262
01263 if (NotFailed)
01264 NotFailed = CopyEditedPathBack();
01265
01266
01267 if (NotFailed)
01268 NotFailed = FillPathIfEndsSnapped();
01269 if (NotFailed)
01270 NotFailed = JoinWithOtherPath();
01271
01272 if (NotFailed)
01273 {
01274
01275 OriginalPath->InvalidateBoundingRect();
01276 SelRange *Sel = GetApplication()->FindSelection();
01277 Sel->UpdateBounds();
01278
01279
01280 DocRect NewBounds = Sel->GetBoundingRect(TRUE);
01281 ERROR3IF(pSpread == NULL, "Unexpectedly NULL spread pointer");
01282 pSpread->ExpandPasteboardToInclude(NewBounds);
01283
01284
01285 NotFailed = RecordBoundsAction::DoRecord(this, &UndoActions, OriginalPath, OptimiseRedraw) != AC_FAIL;
01286 }
01287 }
01288 }
01289
01290
01291
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
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
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
01355 BOOL* pDragStarted = (BOOL*) (pCurrentDragS->pNode);
01356
01357 if (*pDragStarted == TRUE)
01358 {
01359 RenderDraggingBlobs( pEditPath, 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
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
01383 GetApplication()->FindSelection()->Update();
01384
01385
01386 FailAndExecute();
01387 End();
01388 return;
01389 }
01390 }
01391 else
01392 {
01393
01394
01395
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
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 BOOL OptimiseRedraw = CopyNeedToRenderFlags(pOrigPath, pEditPath) && !(EndSnapped || SnapToAnother);
01415 if (!IS_A(pOrigPath,NodePath))
01416 OptimiseRedraw = FALSE;
01417
01418
01419 if (pAttrBrush != NULL)
01420 OptimiseRedraw = FALSE;
01421
01422
01423
01424 if (NotFailed)
01425 NotFailed = RecalcBoundsAction::DoRecalc(this, &UndoActions, pOrigPath, OptimiseRedraw) != AC_FAIL;
01426
01427
01428
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
01438
01439 if (NotFailed && EndSnapped)
01440 {
01441 SnapEndsTogether (pEditPath);
01442 }
01443 }
01444
01445
01446 if (NotFailed)
01447 NotFailed = CopyEditedPathBack(pOrigPath, pEditPath);
01448
01449 if (pCurrentOrig == (NodeListItem*) OriginalPaths.GetHead ())
01450 {
01451
01452 if (NotFailed)
01453 NotFailed = FillPathIfEndsSnapped(pOrigPath);
01454 }
01455
01456
01457
01458
01459
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 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
01485 pOrigPath->InvalidateBoundingRect();
01486 SelRange *Sel = GetApplication()->FindSelection();
01487 Sel->UpdateBounds();
01488
01489
01490 DocRect NewBounds = Sel->GetBoundingRect();
01491 ERROR3IF(pSpread == NULL, "Unexpectedly NULL spread pointer");
01492 pSpread->ExpandPasteboardToInclude(NewBounds);
01493
01494 if (!useHeadPath)
01495 {
01496
01497 NotFailed = RecordBoundsAction::DoRecord(this, &UndoActions, pOrigPath, OptimiseRedraw) != AC_FAIL;
01498 }
01499 else
01500 {
01501
01502
01503
01504
01505 NotFailed = RecordBoundsAction::DoRecord(this, &UndoActions, (*hHeadPath), OptimiseRedraw) != AC_FAIL;
01506 }
01507 }
01508 }
01509 }
01510
01511
01512
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
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
01549
01550
01551 pCurrentEdit = (NodeListItem*) EditPaths.GetHead ();
01552 pCurrentChange = (NodeListItem*) ObjChanges.GetHead ();
01553 pCurrentDragS = (NodeListItem*) PathsDragStarted.GetHead ();
01554
01555 while ( (pCurrentEdit) && (pCurrentChange) && (pCurrentDragS))
01556 {
01557
01558 Path* pEditPath = (Path*) (pCurrentEdit->pNode);
01559 ObjChangePathEdit* pObjChange = (ObjChangePathEdit*) (pCurrentChange->pNode);
01560 BOOL* pDragStarted = (BOOL*) (pCurrentDragS->pNode);
01561
01562
01563 delete (pEditPath);
01564 delete (pObjChange);
01565 delete (pDragStarted);
01566
01567
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 }
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 BOOL OpNodePathEditBlob::InsertChangeBlendStepsAction(NodeBlend* pNodeBlend)
01602 {
01603 ERROR2IF(pNodeBlend==NULL, FALSE, "NodeBlend pointer is NULL");
01604
01605
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
01627
01628
01629 if (ok)
01630 {
01631 double PathDistanceUsed = NewNumSteps * StepDistance;
01632 double PathProportion = PathDistanceUsed / NewPathLength;
01633
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;
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 }
01669 }
01670 }
01671 return TRUE;
01672 }
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692 void OpNodePathEditBlob::SnapEndsTogether()
01693 {
01694
01695
01696 PathVerb* Verbs = EditPath.GetVerbArray();
01697 PathFlags* Flags = EditPath.GetFlagArray();
01698 INT32 NumCoords = EditPath.GetNumCoords();
01699
01700
01701 INT32 pos;
01702 for( pos = 0; pos < NumCoords && !( Flags[pos].IsEndPoint && Flags[pos].IsSelected); pos++ );
01703
01704
01705
01706
01707
01708
01709
01710
01711 INT32 startpos = pos;
01712 EditPath.FindStartOfSubPath(&startpos);
01713
01714 pos=startpos;
01715 EditPath.FindEndOfSubPath(&pos);
01716
01717
01718
01719 if (Verbs[pos] == PT_BEZIERTO)
01720 pos+=2;
01721
01722
01723 Verbs[pos] |= PT_CLOSEFIGURE;
01724
01725
01726 Flags[pos].IsSelected = TRUE;
01727
01728 if ((Verbs[pos] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
01729 {
01730 Flags[pos-1].IsSelected = TRUE;
01731
01732
01733
01734
01735 if (!Flags[pos-1].IsSmooth)
01736 Flags[pos-1].IsRotate = FALSE;
01737
01738
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
01749 if (!Flags[pos+1].IsSmooth)
01750 Flags[pos+1].IsRotate = FALSE;
01751
01752 if (!Flags[pos].IsSmooth)
01753 Flags[pos].IsRotate = FALSE;
01754 }
01755 }
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775 void OpNodePathEditBlob::SnapEndsTogether(Path* pEditPath)
01776 {
01777
01778
01779 PathVerb* Verbs = pEditPath->GetVerbArray();
01780 PathFlags* Flags = pEditPath->GetFlagArray();
01781 INT32 NumCoords = pEditPath->GetNumCoords();
01782
01783
01784 INT32 pos;
01785 for ( pos = 0;pos<NumCoords && !(Flags[pos].IsEndPoint && Flags[pos].IsSelected);pos++);
01786
01787
01788
01789
01790
01791
01792
01793
01794 INT32 startpos = pos;
01795 pEditPath->FindStartOfSubPath(&startpos);
01796
01797 pos=startpos;
01798 pEditPath->FindEndOfSubPath(&pos);
01799
01800
01801
01802 if (Verbs[pos] == PT_BEZIERTO)
01803 pos+=2;
01804
01805
01806 Verbs[pos] |= PT_CLOSEFIGURE;
01807
01808
01809 Flags[pos].IsSelected = TRUE;
01810
01811 if ((Verbs[pos] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
01812 {
01813 Flags[pos-1].IsSelected = TRUE;
01814
01815
01816
01817
01818 if (!Flags[pos-1].IsSmooth)
01819 Flags[pos-1].IsRotate = FALSE;
01820
01821
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
01832 if (!Flags[pos+1].IsSmooth)
01833 Flags[pos+1].IsRotate = FALSE;
01834
01835 if (!Flags[pos].IsSmooth)
01836 Flags[pos].IsRotate = FALSE;
01837 }
01838 }
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856 BOOL OpNodePathEditBlob::JoinWithOtherPath()
01857 {
01858
01859 if (!SnapToAnother)
01860 return TRUE;
01861
01862
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
01876
01877 ENSURE(MainIndex<NumCoords,"There isn't a selected endpoint in the original path (JoinWithAnotherPath)");
01878
01879
01880
01881
01882 Node* pnp;
01883 OriginalPath->NodeCopy(&pnp);
01884 NodePath* MainPath = (NodePath*)pnp;
01885
01886 if (!MainPath)
01887 return FALSE;
01888
01889
01890
01891 if (SnapToAnother)
01892 {
01893
01894
01895 if (SnapToPath == OriginalPath)
01896 SnapToPath = MainPath;
01897
01898
01899
01900
01901
01902 if (SnapToLineOrCurve)
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
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
01942 if (!DoInsertNewNode(MainPath, OriginalPath, NEXT, TRUE, FALSE))
01943 {
01944 MainPath->CascadeDelete();
01945 delete MainPath;
01946 return FALSE;
01947 }
01948
01949
01950 if (!DoHideNode(OriginalPath, TRUE))
01951 return FALSE;
01952
01953
01954 if (OldSnapPath != OriginalPath)
01955 {
01956 if (!DoHideNode(OldSnapPath, TRUE))
01957 return FALSE;
01958 }
01959
01960
01961 OriginalPath = MainPath;
01962
01963 return TRUE;
01964 }
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984 BOOL OpNodePathEditBlob::JoinWithOtherPath(NodePath** pOrigPath)
01985 {
01986
01987 if (!SnapToAnother)
01988 return TRUE;
01989
01990
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
02004
02005 ENSURE(MainIndex<NumCoords,"There isn't a selected endpoint in the original path (JoinWithAnotherPath)");
02006
02007
02008
02009
02010 Node* pnp;
02011 (*pOrigPath)->NodeCopy(&pnp);
02012 NodePath* MainPath = (NodePath*)pnp;
02013
02014 if (!MainPath)
02015 return FALSE;
02016
02017
02018
02019 if (SnapToAnother)
02020 {
02021
02022
02023 if (SnapToPath == (*pOrigPath))
02024 SnapToPath = MainPath;
02025
02026
02027
02028
02029
02030 if (SnapToLineOrCurve)
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
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
02070 if (!DoInsertNewNode(MainPath, (*pOrigPath), NEXT, TRUE, FALSE))
02071 {
02072 MainPath->CascadeDelete();
02073 delete MainPath;
02074 return FALSE;
02075 }
02076
02077
02078 if (!DoHideNode((*pOrigPath), TRUE))
02079 return FALSE;
02080
02081
02082 if (OldSnapPath != (*pOrigPath))
02083 {
02084 if (!DoHideNode(OldSnapPath, TRUE))
02085 return FALSE;
02086 }
02087
02088
02089 (*pOrigPath) = MainPath;
02090
02091 return TRUE;
02092 }
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 BOOL OpNodePathEditBlob::BuildEditPaths ()
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
02124 UINT32 LastEndPoint = 0;
02125 BOOL SetNextEndPoint = FALSE;
02126 BOOL SetNextNextEndPoint = FALSE;
02127 PathFlags* Flags = NewEditPath->GetFlagArray();
02128
02129 for (UINT32 i=0; i<NumCoords; i++)
02130 {
02131
02132 Flags[i].NeedToRender = FALSE;
02133
02134 if (Flags[i].IsEndPoint)
02135 {
02136
02137
02138 if (SetNextNextEndPoint)
02139 {
02140 Flags[i].NeedToRender = TRUE;
02141 SetNextNextEndPoint = FALSE;
02142 }
02143
02144
02145 if (SetNextEndPoint)
02146 {
02147
02148 Flags[i].NeedToRender = TRUE;
02149 SetNextEndPoint = FALSE;
02150
02151
02152 if (Flags[i].IsRotate || Flags[i].IsSmooth)
02153 SetNextNextEndPoint = TRUE;
02154 }
02155
02156
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
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);
02175
02176 pCurrent = (NodeListItem*) OriginalPaths.GetNext (pCurrent);
02177
02178
02179
02180
02181 }
02182
02183 return (TRUE);
02184 }
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197 BOOL OpNodePathEditBlob::BuildEditPath()
02198 {
02199
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
02207 UINT32 LastEndPoint = 0;
02208 BOOL SetNextEndPoint = FALSE;
02209 BOOL SetNextNextEndPoint = FALSE;
02210 PathFlags* Flags = EditPath.GetFlagArray();
02211 for (UINT32 i=0; i<NumCoords; i++)
02212 {
02213
02214 Flags[i].NeedToRender = FALSE;
02215
02216 if (Flags[i].IsEndPoint)
02217 {
02218
02219
02220 if (SetNextNextEndPoint)
02221 {
02222 Flags[i].NeedToRender = TRUE;
02223 SetNextNextEndPoint = FALSE;
02224 }
02225
02226
02227 if (SetNextEndPoint)
02228 {
02229
02230 Flags[i].NeedToRender = TRUE;
02231 SetNextEndPoint = FALSE;
02232
02233
02234 if (Flags[i].IsRotate || Flags[i].IsSmooth)
02235 SetNextNextEndPoint = TRUE;
02236 }
02237
02238
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
02246 SetNextEndPoint = TRUE;
02247 }
02248
02249 LastEndPoint = i;
02250 }
02251 }
02252
02253 return TRUE;
02254 }
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269 BOOL OpNodePathEditBlob::CopyEditedPathBack()
02270 {
02271
02272
02273
02274
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
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
02297 {
02298
02299 if (FirstChanged == -1)
02300 FirstChanged = i;
02301
02302
02303 LastChanged = i;
02304 }
02305 }
02306
02307 }
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318 if (ChangedElements > 0)
02319 {
02320
02321
02322
02323
02324 if (DragPoint != -1)
02325 {
02326
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
02354
02355 if ((Act!=AC_NORECORD) && (ModAction!=NULL))
02356 {
02357
02358
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
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
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 }
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441 BOOL OpNodePathEditBlob::CopyEditedPathBack(NodePath* pOrigPath, Path* pEditPath)
02442 {
02443
02444
02445
02446
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
02468
02469
02470
02471
02472
02473
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
02494
02495 if ((Act!=AC_NORECORD) && (ModAction!=NULL))
02496 {
02497
02498
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
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
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 }
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583 BOOL OpNodePathEditBlob::CopyNeedToRenderFlags()
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 }
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618 BOOL OpNodePathEditBlob::CopyNeedToRenderFlags(NodePath* pOrigPath, Path* pEditPath)
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 }
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658 void OpNodePathEditBlob::RecalculatePath( DocCoord Offset, BOOL SnapEnds , INT32 SnapIndex)
02659 {
02660
02661 PathFlags* Flags = EditPath.GetFlagArray();
02662 DocCoord* Coords = EditPath.GetCoordArray();
02663
02664 INT32 NumCoords = EditPath.GetNumCoords();
02665
02666
02667 for (INT32 i=0; i<NumCoords; i++)
02668 {
02669
02670 if (Flags[i].IsSelected)
02671 Coords[i].translate( Offset.x, Offset.y );
02672 }
02673
02674
02675 EditPath.SmoothCurve(TRUE, SnapEnds, SnapIndex);
02676
02677
02678
02679
02680 if (SnapToAnother)
02681 {
02682
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
02691
02692
02693
02694
02695 if (Verbs[SnapIndex] == PT_MOVETO)
02696 {
02697
02698 if (Verbs[SnapIndex+1] == PT_BEZIERTO)
02699 {
02700
02701 if (OtherVerbs[SnapToIndex] == PT_MOVETO)
02702 {
02703
02704 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO)
02705 {
02706
02707
02708 if (Flags[SnapIndex+1].IsSmooth)
02709 Coords[SnapIndex+1] = EditPath.SmoothControlPoint( SnapIndex+1,
02710 FALSE,
02711 TRUE,
02712 TRUE,
02713 OtherCoords[SnapToIndex+3]
02714 );
02715
02716
02717
02718
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
02735 if (Flags[SnapIndex+1].IsSmooth)
02736 Coords[SnapIndex+1] = EditPath.SmoothControlPoint( SnapIndex+1,
02737 FALSE,
02738 TRUE,
02739 FALSE,
02740 OtherCoords[SnapToIndex+1]
02741 );
02742
02743 SnapToLineOrCurve = FALSE;
02744
02745 }
02746 }
02747 else
02748 {
02749
02750 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO)
02751 {
02752
02753
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
02762 if ((SnapToLineOrCurve = OtherFlags[SnapToIndex-1].IsSmooth))
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
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
02786 SnapToLineOrCurve = FALSE;
02787 }
02788 }
02789
02790 }
02791 else
02792 {
02793
02794 if (OtherVerbs[SnapToIndex] == PT_MOVETO)
02795 {
02796
02797 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO)
02798 {
02799
02800
02801
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
02817
02818 SnapToLineOrCurve = FALSE;
02819 }
02820 }
02821 else
02822 {
02823
02824 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO)
02825 {
02826
02827
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
02844
02845 SnapToLineOrCurve = FALSE;
02846 }
02847 }
02848
02849 }
02850 }
02851 else
02852 {
02853
02854 if (Verbs[SnapIndex] == PT_BEZIERTO)
02855 {
02856
02857 if (OtherVerbs[SnapToIndex] == PT_MOVETO)
02858 {
02859
02860 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO)
02861 {
02862
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
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
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
02896 SnapToLineOrCurve = FALSE;
02897 }
02898 }
02899 else
02900 {
02901
02902 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO)
02903 {
02904
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
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
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
02937 SnapToLineOrCurve = FALSE;
02938 }
02939 }
02940
02941 }
02942 else
02943 {
02944
02945 if (OtherVerbs[SnapToIndex] == PT_MOVETO)
02946 {
02947
02948 if (OtherVerbs[SnapToIndex+1] == PT_BEZIERTO)
02949 {
02950
02951
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
02967
02968 SnapToLineOrCurve = FALSE;
02969 }
02970 }
02971 else
02972 {
02973
02974 if (OtherVerbs[SnapToIndex] == PT_BEZIERTO)
02975 {
02976
02977
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
02994
02995 SnapToLineOrCurve = FALSE;
02996 }
02997 }
02998
02999 }
03000 }
03001
03002 }
03003
03004 }
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027 void OpNodePathEditBlob::RecalculatePaths (Path* pEditPath, DocCoord Offset, BOOL SnapEnds , INT32 SnapIndex)
03028 {
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038 PathFlags* Flags = pEditPath->GetFlagArray();
03039 DocCoord* Coords = pEditPath->GetCoordArray();
03040
03041 INT32 NumCoords = pEditPath->GetNumCoords();
03042
03043
03044 for (INT32 i=0; i<NumCoords; i++)
03045 {
03046
03047 if (Flags[i].IsSelected)
03048 Coords[i].translate( Offset.x, Offset.y );
03049 }
03050
03051
03052 pEditPath->SmoothCurve(TRUE, SnapEnds, SnapIndex);
03053
03054
03055
03056
03057 }
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069 void OpNodePathEditBlob::RenderDragBlobs( DocRect Rect, Spread *pSpread, BOOL bSolidDrag )
03070 {
03071 RenderPathEditBlobs(Rect,pSpread);
03072 if (EditObjChange.ChangeMask.EorBlobs)
03073 EditObjChange.RenderCurrentBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE);
03074 }
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085 void OpNodePathEditBlob::RenderDraggingBlobs ( DocRect Rect, Spread *pSpread )
03086 {
03087 RenderPathEditBlobs(Rect, pSpread);
03088 }
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100 void OpNodePathEditBlob::RenderDraggingBlobs ( Path* pEditPath, Spread *pSpread )
03101 {
03102 RenderPathEditBlobs(pEditPath, pSpread);
03103 }
03104
03105
03106 void OpNodePathEditBlob::RenderPathEditBlobs( DocRect Rect, Spread *pSpread )
03107 {
03108
03109 Path RenderPath;
03110 if ( RenderPath.Initialise(24, 12) == FALSE )
03111 {
03112
03113 return;
03114 }
03115
03116 BOOL IsInCurve = FALSE;
03117 INT32 NumCoords = EditPath.GetNumCoords();
03118 for (INT32 i=0; i<NumCoords; i++)
03119 {
03120
03121 PathFlags* Flags = EditPath.GetFlagArray();
03122 DocCoord* Coords = EditPath.GetCoordArray();
03123 PathVerb* Verbs = EditPath.GetVerbArray();
03124
03125
03126 if (Flags[i].IsEndPoint)
03127 {
03128 if (IsInCurve)
03129 {
03130
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
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
03182 if (SnapToLineOrCurve)
03183 {
03184
03185 RenderPath.InsertMoveTo(SnapToCoords[0]);
03186 RenderPath.InsertCurveTo(SnapToCoords[1],SnapToCoords[2],SnapToCoords[3]);
03187 }
03188
03189
03190 if (RenderPath.GetNumCoords()==0)
03191 return;
03192
03193
03194 RenderRegion* pRegion = DocView::RenderOnTop( NULL, StartSpread, ClippedEOR );
03195 while (pRegion != NULL)
03196 {
03197 pRegion->SetLineColour( COLOUR_XORNEW );
03198 pRegion->DrawPath( &RenderPath );
03199 pRegion = DocView::GetNextOnTop( &Rect );
03200 }
03201 }
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213 void OpNodePathEditBlob::RenderPathEditBlobs( Path* pEditPath, Spread *pSpread )
03214 {
03215
03216 Path RenderPath;
03217 if ( RenderPath.Initialise(24, 12) == FALSE )
03218 {
03219
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
03230 PathFlags* Flags = pEditPath->GetFlagArray();
03231 DocCoord* Coords = pEditPath->GetCoordArray();
03232 PathVerb* Verbs = pEditPath->GetVerbArray();
03233
03234
03235 if (Flags[i].IsEndPoint)
03236 {
03237 if (IsInCurve)
03238 {
03239
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
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
03291 if (SnapToLineOrCurve)
03292 {
03293
03294 RenderPath.InsertMoveTo(SnapToCoords[0]);
03295 RenderPath.InsertCurveTo(SnapToCoords[1],SnapToCoords[2],SnapToCoords[3]);
03296 }
03297
03298
03299 if (RenderPath.GetNumCoords()==0)
03300 return;
03301
03302
03303 RenderRegion* pRegion = DocView::RenderOnTop( NULL, StartSpread, ClippedEOR );
03304 while (pRegion != NULL)
03305 {
03306 pRegion->SetLineColour( COLOUR_XORNEW );
03307 pRegion->DrawPath( &RenderPath );
03308 pRegion = DocView::GetNextOnTop( &Rect );
03309 }
03310 }
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325 BOOL OpNodePathEditBlob::Init()
03326 {
03327 return (RegisterOpDescriptor( 0,
03328 _R(IDS_NODEPATH_EDIT),
03329 CC_RUNTIME_CLASS(OpNodePathEditBlob),
03330 OPTOKEN_NODEPATH,
03331 OpNodePathEditBlob::GetState,
03332 0,
03333 _R(IDBBL_NODEPATHOP),
03334 0 ) );
03335 }
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351 OpState OpNodePathEditBlob::GetState(String_256* Description, OpDescriptor*)
03352 {
03353 OpState Blobby;
03354
03355 return Blobby;
03356 }
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367 void OpNodePathEditBlob::SetStatusLineHelp()
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 }
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403 void OpNodePathEditControlBlob::DoStartDragEdit(NodePath* OrigPath, DocCoord Anchor,
03404 Spread *pSpread, INT32 ControlIndex)
03405 {
03406
03407 LastMousePos = Anchor;
03408 StartMousePos = Anchor;
03409 StartSpread = pSpread;
03410 OriginalPath = OrigPath;
03411 Index = ControlIndex;
03412 BOOL ok = TRUE;
03413
03414 PathFlags* Flags = OrigPath->InkPath.GetFlagArray();
03415 PathVerb* Verbs = OrigPath->InkPath.GetVerbArray();
03416 DocCoord* Coords = OrigPath->InkPath.GetCoordArray();
03417
03418
03419 if (Flags[Index-1].IsEndPoint)
03420 EndPointIndex = Index-1;
03421 else
03422 EndPointIndex = Index+1;
03423 ConstrainPoint = Coords[EndPointIndex];
03424 ConstrainPrevPoint = ConstrainPoint;
03425 ConstrainNextPoint = ConstrainPoint;
03426
03427
03428 OppositeIndex = OrigPath->InkPath.FindOppositeControlPoint(Index);
03429
03430
03431 if (ok)
03432 ok = BuildEditPath();
03433
03434
03435 if (ok)
03436 ok = EditObjChange.ObjChangeStarting(OrigPath,this,&EditPath,StartSpread,TRUE) == CC_OK;
03437
03438 if (ok)
03439 ok = CreateCursors();
03440 if (ok)
03441 ChangeCursor(pCrossHairCursor);
03442
03443
03444
03445 if (ok)
03446 {
03447 Flags = EditPath.GetFlagArray();
03448 Verbs = EditPath.GetVerbArray();
03449
03450 Flags[ControlIndex].IsSmooth = FALSE;
03451 if (OppositeIndex >= 0)
03452 Flags[OppositeIndex].IsSmooth = FALSE;
03453 Flags[EndPointIndex].IsSmooth = FALSE;
03454 }
03455
03456
03457 if (ok)
03458 {
03459 DocRect EditPathBBox = EditPath.GetBoundingRect();
03460 RenderPathEditControlBlobs(EditPathBBox, pSpread);
03461 DragStarted = TRUE;
03462
03463
03464 ok = StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos);
03465 }
03466
03467 if (!ok)
03468 {
03469 InformError();
03470 FailAndExecute();
03471 End();
03472 }
03473 }
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493 void OpNodePathEditControlBlob::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, Spread *pSpread, BOOL bSolidDrag)
03494 {
03495 EndSnapped = FALSE;
03496
03497
03498
03499 if (pSpread != StartSpread)
03500 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
03501
03502 Path TempPath;
03503
03504
03505 if (EditObjChange.ChangeMask.EorBlobs)
03506 {
03507 ChangeCode Chge=EditObjChange.RenderCurrentBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE);
03508 if (Chge!=CC_OK)
03509 return;
03510
03511 if (!TempPath.Initialise(EditPath.GetNumCoords(), 12))
03512 return;
03513 TempPath.CopyPathDataFrom(&EditPath);
03514 }
03515
03516
03517 ERROR3IF(ConstrainPoint == DocCoord(-1,-1),"ConstrainPoint wasn't set");
03518 if (ClickMods.Constrain)
03519 DocView::ConstrainToAngle(ConstrainPoint, &PointerPos);
03520 DocView::SnapCurrent(StartSpread, &PointerPos);
03521
03522
03523 RenderPathEditControlBlobs( EditPath.GetBoundingRect(), StartSpread );
03524
03525
03526
03527 DocCoord Offset;
03528 Offset.x = PointerPos.x - LastMousePos.x;
03529 Offset.y = PointerPos.y - LastMousePos.y;
03530 RecalculatePath( Offset );
03531
03532 if (EditObjChange.ChangeMask.EorBlobs)
03533 {
03534 ChangeCode Chge=EditObjChange.RenderChangedBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE);
03535 if (Chge!=CC_OK)
03536 {
03537
03538 EditPath.CopyPathDataFrom(&TempPath);
03539 RenderPathEditControlBlobs( EditPath.GetBoundingRect(), StartSpread );
03540 return;
03541 }
03542 }
03543
03544
03545 LastMousePos = PointerPos;
03546 RenderPathEditControlBlobs( EditPath.GetBoundingRect(), StartSpread );
03547
03548
03549
03550 PathFlags* Flags = EditPath.GetFlagArray();
03551
03552 INT32 CurrentIndex;
03553
03554 if (Flags[Index+1].IsEndPoint)
03555 {
03556 CurrentIndex = Index+1;
03557 }
03558 else
03559 {
03560 CurrentIndex = Index-1;
03561 }
03562
03563
03564 BROADCAST_TO_ALL(PathEditedMsg(&EditPath, pSpread, CurrentIndex));
03565
03566 SetStatusLineHelp();
03567 }
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584 BOOL OpNodePathEditControlBlob::BuildEditPath()
03585 {
03586
03587 const INT32 NumCoords = OriginalPath->InkPath.GetNumCoords();
03588 if (!EditPath.Initialise(NumCoords, 24))
03589 return FALSE;
03590 if (!EditPath.CopyPathDataFrom(&(OriginalPath->InkPath)))
03591 return FALSE;
03592 EditPath.ClearNeedToRender();
03593
03594 PathFlags* Flags = EditPath.GetFlagArray();
03595
03596
03597 if (Flags[Index-1].IsEndPoint)
03598 Flags[Index+2].NeedToRender = TRUE;
03599 else
03600 Flags[Index+1].NeedToRender = TRUE;
03601
03602
03603 if (Flags[EndPointIndex].IsRotate && OppositeIndex>=0 && OppositeIndex<NumCoords)
03604 {
03605 if (Flags[OppositeIndex-1].IsEndPoint)
03606 Flags[OppositeIndex+2].NeedToRender = TRUE;
03607 else
03608 Flags[OppositeIndex+1].NeedToRender = TRUE;
03609 }
03610
03611
03612 Flags[EndPointIndex].IsSmooth = FALSE;
03613
03614 return TRUE;
03615 }
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632 void OpNodePathEditControlBlob::RecalculatePath( DocCoord Offset )
03633 {
03634
03635 DocCoord* Coords = EditPath.GetCoordArray();
03636 PathFlags* Flags = EditPath.GetFlagArray();
03637 INT32 NumCoords = EditPath.GetNumCoords();
03638 if (Flags[EndPointIndex].IsRotate && OppositeIndex >=0 && OppositeIndex < NumCoords)
03639 {
03640 EditPath.CalcRotate(Coords[EndPointIndex], &Coords[Index], &Coords[OppositeIndex], Offset);
03641 }
03642 else
03643 {
03644 Coords[Index].x += Offset.x;
03645 Coords[Index].y += Offset.y;
03646 }
03647 }
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661 void OpNodePathEditControlBlob::RenderDragBlobs(DocRect Rect, Spread *pSpread, BOOL bSolidDrag)
03662 {
03663
03664 if (LastMousePos == StartMousePos) return;
03665
03666
03667 RenderPathEditControlBlobs(Rect,pSpread);
03668
03669
03670 if (EditObjChange.ChangeMask.EorBlobs)
03671 EditObjChange.RenderCurrentBlobs(OriginalPath,this,&EditPath,StartSpread,TRUE);
03672 }
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683 void OpNodePathEditControlBlob::RenderDraggingBlobs ( DocRect Rect, Spread *pSpread )
03684 {
03685 RenderPathEditControlBlobs(Rect, pSpread);
03686 }
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703 void OpNodePathEditControlBlob::RenderPathEditControlBlobs( DocRect Rect, Spread *pSpread )
03704 {
03705 if (LastMousePos == StartMousePos)
03706 return;
03707
03708 DocCoord* Coords = EditPath.GetCoordArray();
03709 PathFlags* Flags = EditPath.GetFlagArray();
03710
03711 INT32 NumCoords = EditPath.GetNumCoords();
03712
03713
03714 DocCoord StartCoord = Coords[0];
03715
03716
03717 RenderRegion* pRegion = DocView::RenderOnTop( NULL, StartSpread, ClippedEOR );
03718 while ( pRegion )
03719 {
03720 OpNodePathEditBlob::RenderPathEditBlobs(Rect, pSpread);
03721
03722 EditPath.DrawControlBlob(pRegion, Coords[Index]);
03723 EditPath.DrawControlLine(pRegion, Coords[Index], Coords[EndPointIndex]);
03724 if (Flags[EndPointIndex].IsRotate && OppositeIndex>=0 && OppositeIndex<NumCoords && Flags[Index].IsSelected)
03725 {
03726
03727 EditPath.DrawControlBlob(pRegion, Coords[OppositeIndex]);
03728 EditPath.DrawControlLine(pRegion, Coords[OppositeIndex], Coords[EndPointIndex]);
03729 }
03730
03731
03732 pRegion = DocView::GetNextOnTop( &Rect );
03733
03734 }
03735 }
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748 BOOL OpNodePathEditControlBlob::Init()
03749 {
03750 PORTNOTETRACE("other","OpNodePathEditControlBlob::Init - do nothing");
03751 return (RegisterOpDescriptor(
03752 0,
03753 _R(IDS_NODEPATH_EDIT),
03754 CC_RUNTIME_CLASS(OpNodePathEditControlBlob),
03755 OPTOKEN_NODEPATH,
03756 OpNodePathEditControlBlob::GetState,
03757 0,
03758 _R(IDBBL_NODEPATHOP),
03759 0 ) );
03760 }
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777 OpState OpNodePathEditControlBlob::GetState(String_256* Description, OpDescriptor*)
03778 {
03779 OpState Blobby;
03780
03781 return Blobby;
03782 }
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793 void OpNodePathEditControlBlob::SetStatusLineHelp()
03794 {
03795 String_256 HelpString(_R(IDS_PATHDRAGFINISHCONTROL));
03796 GetApplication()->UpdateStatusBarText(&HelpString, FALSE);
03797 }
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815 NodeGroup* OpNodePathEditBlob::GetGroupParentOfCurve()
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 }
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852 NodeGroup* OpNodePathEditBlob::GetGroupParentOfCurve(NodePath* pOrigPath)
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 }
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889 AttrBrushType* OpNodePathEditBlob::GetAppliedBrush()
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
03901 if (((AttrBrushType*)pAttr)->GetBrushHandle() != BrushHandle_NoBrush)
03902 pAttrBrush = (AttrBrushType*)pAttr;
03903 }
03904 return pAttrBrush;
03905 }
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927 BOOL OpNodePathEditBlob::EditBrushAttribute(INT32 FirstIndex, INT32 LastIndex, AttrBrushType* pAttrBrush)
03928 {
03929 if (FirstIndex < 0 || LastIndex < 0 || LastIndex <= FirstIndex || pAttrBrush == NULL)
03930 {
03931
03932 return FALSE;
03933 }
03934
03935
03936
03937 CDistanceSampler* pDistSamp = pAttrBrush->GetPressureCache();
03938 if (pDistSamp == NULL)
03939 return TRUE;
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950 MILLIPOINT ChangedLength = GetLengthOfPathSection(&EditPath, FirstIndex, LastIndex);
03951
03952
03953
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
03963
03964 CDistanceSampler* pSection = new CDistanceSampler;
03965 if (pSection == NULL)
03966 return FALSE;
03967
03968
03969 BOOL ok = pDistSamp->GetDataSection(OrigStartDist, OrigEndDist, pSection);
03970 if (!ok)
03971 return FALSE;
03972
03973
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
03991 RemovePressurePointsAction* pAction;
03992
03993 if (RemovePressurePointsAction::Init(this, &UndoActions, pAttrBrush, StartPressIndex, NumIndexes, NULL, &pAction) == AC_FAIL)
03994 return FALSE;
03995
03996
03997 AddPressurePointsAction* pAddAction;
03998
03999
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 }
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035 MILLIPOINT OpNodePathEditBlob::GetLengthOfPathSection(Path* pPath, INT32 FirstIndex, INT32 LastIndex)
04036 {
04037 ERROR2IF(pPath == NULL, -1, "Path is NULL in OpNodePathEditBlob::GetLengthOfPathSection");
04038
04039
04040 INT32 NumElements = pPath->GetNumCoords();
04041
04042
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
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
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 }
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088 INT32 OpNodePathEditBlob::GetDistanceToPathIndex(Path* pPath, INT32 Index)
04089 {
04090
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
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 }
04111
04112
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123
04124 BOOL OpNodePathAddEndpoint::Init()
04125 {
04126 return (RegisterOpDescriptor( 0,
04127 _R(IDS_NODEPATH_ADDENDPOINT),
04128 CC_RUNTIME_CLASS(OpNodePathAddEndpoint),
04129 OPTOKEN_ADDENDPOINT,
04130 OpNodePathAddEndpoint::GetState,
04131 0,
04132 _R(IDBBL_NODEPATHOP),
04133 0 ) );
04134 }
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151 OpState OpNodePathAddEndpoint::GetState(String_256* Description, OpDescriptor*)
04152 {
04153 OpState Blobby;
04154
04155 return Blobby;
04156 }
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167 void OpNodePathAddEndpoint::SetStatusLineHelp()
04168 {
04169 String_256 HelpString;
04170 if (EndSnapped)
04171 HelpString = String_256(_R(IDS_PATHDRAGCREATESHAPE));
04172 else
04173 {
04174 if (SnapToAnother)
04175 HelpString = String_256(_R(IDS_PATHDRAGJOINPATHS));
04176 else
04177 HelpString = String_256(_R(IDS_PATHDRAGADDSEGMENT));
04178 }
04179
04180 GetApplication()->UpdateStatusBarText(&HelpString, FALSE);
04181 }
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213 void OpNodePathAddEndpoint::DoStartDragEdit(NodePath* OrigPath,
04214 DocCoord Anchor,
04215 Spread *pSpread,
04216 ClickModifiers Mods,
04217 INT32 PathIndex,
04218 BOOL CurveOrLine,
04219 BOOL CloseThePath,
04220 BOOL SmoothOrCusp)
04221 {
04222
04223 InsertPosition = PathIndex;
04224 OriginalPath = OrigPath;
04225
04226
04227 StartMousePos = Anchor;
04228 LastMousePos = Anchor;
04229 StartSpread = pSpread;
04230 IsPathClosing = CloseThePath;
04231 AddCurveFlag = CurveOrLine;
04232 AddSmoothFlag = SmoothOrCusp;
04233
04234
04235 PathFlags* Flags = OrigPath->InkPath.GetFlagArray();
04236 PathVerb* Verbs = OrigPath->InkPath.GetVerbArray();
04237 DocCoord* Coords = OrigPath->InkPath.GetCoordArray();
04238 if (Verbs[InsertPosition] == PT_MOVETO)
04239 ConstrainPoint = Coords[InsertPosition];
04240 else
04241 {
04242 INT32 Temp = InsertPosition;
04243 while (!Flags[Temp].IsEndPoint && (Temp < OrigPath->InkPath.GetNumCoords()))
04244 Temp++;
04245 ConstrainPoint = Coords[Temp];
04246 }
04247 ConstrainPrevPoint = ConstrainPoint;
04248 ConstrainNextPoint = ConstrainPoint;
04249
04250
04251 ERROR3IF(ConstrainPoint == DocCoord(-1,-1),"DragConstrainPoint wasn't set");
04252 if (Mods.Constrain)
04253 DocView::ConstrainToAngle(ConstrainPoint, &LastMousePos);
04254 DocView::SnapCurrent(pSpread, &LastMousePos);
04255
04256 BOOL ok = TRUE;
04257
04258
04259 if (ok)
04260 ok = BuildEditPath(LastMousePos);
04261 UpdatePoint = DragPoint;
04262
04263
04264 if (CloseThePath)
04265 {
04266 if (ok)
04267 ok = Complete(StartMousePos);
04268
04269 if (!ok)
04270 {
04271 InformError();
04272 FailAndExecute();
04273 }
04274
04275 End();
04276 return;
04277 }
04278 else
04279 {
04280
04281 if (ok)
04282 ok = CreateCursors();
04283
04284
04285 if (ok)
04286 {
04287 DocRect EditPathBBox = EditPath.GetBoundingRect();
04288
04289
04290
04291 ok = StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos);
04292 }
04293
04294 if (ok)
04295 ChangeCursor(pCrossHairCursor);
04296 }
04297
04298 if (!ok)
04299 {
04300 InformError();
04301 FailAndExecute();
04302 End();
04303 }
04304 }
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322 BOOL OpNodePathAddEndpoint::BuildEditPath(DocCoord NewPoint)
04323 {
04324
04325 INT32 NumCoords = OriginalPath->InkPath.GetNumCoords();
04326
04327
04328 if (!EditPath.Initialise(NumCoords, 24))
04329 return FALSE;
04330
04331
04332 if (!EditPath.CopyPathDataFrom(&(OriginalPath->InkPath)))
04333 return FALSE;
04334
04335 INT32 LastEndPoint = 0;
04336 INT32 LastLastEndPoint = 0;
04337 BOOL SetNextEndPoint = FALSE;
04338 BOOL SetNextNextEndPoint = FALSE;
04339
04340
04341 PathFlags* Flags = EditPath.GetFlagArray();
04342 DocCoord* PathCoords = EditPath.GetCoordArray();
04343 PathVerb* PathVerbs = EditPath.GetVerbArray();
04344
04345
04346 INT32 i;
04347 for ( i=0; i<NumCoords; i++)
04348 {
04349 Flags[i].IsSelected = FALSE;
04350 }
04351
04352
04353
04354
04355
04356 if (!InsertElement(NewPoint, &EditPath, InsertPosition, &NewPointIndex))
04357 return FALSE;
04358
04359
04360 NumCoords = EditPath.GetNumCoords();
04361
04362
04363 Flags = EditPath.GetFlagArray();
04364 PathCoords = EditPath.GetCoordArray();
04365 PathVerbs = EditPath.GetVerbArray();
04366
04367
04368 if (IsPathClosing)
04369 {
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379 if (PathVerbs[NewPointIndex-1] == PT_MOVETO)
04380 {
04381
04382 for (i = NewPointIndex; i < NumCoords && PathVerbs[i] != PT_MOVETO; i++ );
04383
04384 i--;
04385
04386
04387 PathCoords[NewPointIndex-1] = PathCoords[i];
04388
04389
04390 PathVerbs[i] |= PT_CLOSEFIGURE;
04391
04392
04393 Flags[i].IsSelected = TRUE;
04394 }
04395 else
04396 {
04397
04398
04399
04400 INT32 EndCoord = NewPointIndex;
04401
04402 if ((PathVerbs[NewPointIndex] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
04403 EndCoord = NewPointIndex + 2;
04404
04405 PathVerbs[EndCoord] |= PT_CLOSEFIGURE;
04406
04407
04408 i = EndCoord;
04409 do
04410 {
04411 i--;
04412 } while (PathVerbs[i] != PT_MOVETO);
04413
04414 PathCoords[EndCoord] = PathCoords[i];
04415
04416
04417 Flags[i].IsSelected = TRUE;
04418 }
04419 }
04420
04421 EditPath.SmoothCurve();
04422
04423
04424 for (i=0; i<NumCoords; i++)
04425 {
04426
04427 Flags[i].NeedToRender = FALSE;
04428
04429 if (Flags[i].IsEndPoint)
04430 {
04431
04432
04433 if (SetNextNextEndPoint)
04434 {
04435 Flags[i].NeedToRender = TRUE;
04436 SetNextNextEndPoint = FALSE;
04437 }
04438
04439
04440 if (SetNextEndPoint)
04441 {
04442
04443 Flags[i].NeedToRender = TRUE;
04444 SetNextEndPoint = FALSE;
04445
04446
04447 if (Flags[i].IsSmooth)
04448 SetNextNextEndPoint = TRUE;
04449 }
04450
04451
04452 if (Flags[i].IsSelected)
04453 {
04454 Flags[i].NeedToRender = TRUE;
04455 Flags[LastEndPoint].NeedToRender = TRUE;
04456
04457
04458 if (Flags[LastEndPoint].IsSmooth)
04459 Flags[LastLastEndPoint].NeedToRender = TRUE;
04460
04461
04462 SetNextEndPoint = TRUE;
04463 }
04464
04465
04466 LastLastEndPoint = LastEndPoint;
04467 LastEndPoint = i;
04468 }
04469 }
04470
04471
04472 return TRUE;
04473 }
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499 void OpNodePathAddEndpoint::DragFinished( DocCoord Pos,
04500 ClickModifiers Mods,
04501 Spread* pSpread,
04502 BOOL Success,
04503 BOOL bSolidDrag)
04504 {
04505 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
04506 EndDrag();
04507 DestroyCursors();
04508 if ( Success )
04509 {
04510 if (!Complete(Pos))
04511 {
04512 InformError();
04513 FailAndExecute();
04514 }
04515 }
04516 else
04517 FailAndExecute();
04518
04519 End();
04520
04521
04522 }
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539 BOOL OpNodePathAddEndpoint::Complete(DocCoord AddElementPoint)
04540 {
04541 BeginSlowJob();
04542 BOOL ok = TRUE;
04543
04544
04545 if (ok)
04546 ok = DoStartSelOp(TRUE,TRUE);
04547
04548
04549 ObjChangeFlags cFlags;
04550 cFlags.TransformNode = TRUE;
04551 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,OriginalPath,this);
04552 if (ok)
04553 {
04554 if (!OriginalPath->AllowOp(&ObjChange, TRUE))
04555 {
04556 FailAndExecute();
04557 return TRUE;
04558 }
04559 }
04560
04561
04562 if (ok)
04563 ok = CompleteThisPath(AddElementPoint);
04564
04565
04566 if (ok)
04567 {
04568 ObjChange.Define(OBJCHANGE_FINISHED,ObjChangeFlags(),OriginalPath,this);
04569 ok = UpdateChangedNodes(&ObjChange);
04570 }
04571
04572 return ok;
04573 }
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590 BOOL OpNodePathAddEndpoint::CompleteThisPath(DocCoord AddElementPoint)
04591 {
04592 BOOL ok = TRUE;
04593
04594
04595 if (ok)
04596 ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, OriginalPath) != AC_FAIL);
04597
04598
04599
04600
04601
04602
04603 if (ok && EndSnapped)
04604 SnapEndsTogether();
04605
04606
04607
04608 if (ok)
04609 ok = InsertElement(AddElementPoint, &(OriginalPath->InkPath), InsertPosition, &NewPointIndex, TRUE, OriginalPath);
04610
04611
04612 if (ok)
04613 ok = CopyEditedPathBack();
04614
04615 if (IsPathClosing)
04616 EndSnapped = TRUE;
04617
04618
04619 if (ok)
04620 ok = FillPathIfEndsSnapped() && JoinWithOtherPath() ;
04621
04622 if (ok)
04623 {
04624
04625 OriginalPath->InvalidateBoundingRect();
04626
04627
04628 GetApplication()->FindSelection()->UpdateBounds();
04629
04630
04631 ok = (RecordBoundsAction::DoRecord(this, &UndoActions, OriginalPath) != AC_FAIL);
04632 }
04633
04634
04635
04636 NodeGroup* pParent = GetGroupParentOfCurve();
04637
04638 if (pParent != NULL)
04639 {
04640 if (pParent->IS_KIND_OF(NodeBlend))
04641 {
04642 if (ok)
04643 InsertChangeBlendStepsAction((NodeBlend*)pParent);
04644 }
04645
04646 }
04647 ObjChangeFlags cFlags(FALSE,TRUE);
04648 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,cFlags,NULL,this);
04649 ok = UpdateChangedNodes(&ObjChange);
04650
04651 return ok;
04652 }
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676 BOOL OpNodePathAddEndpoint::EditBrushAttribute(INT32 FirstIndex, INT32 LastIndex, AttrBrushType* pAttrBrush)
04677 {
04678 if (FirstIndex < 0 || LastIndex < 0 || LastIndex <= FirstIndex || pAttrBrush == NULL)
04679 {
04680
04681 return FALSE;
04682 }
04683
04684
04685
04686 CDistanceSampler* pDistSamp = pAttrBrush->GetPressureCache();
04687 if (pDistSamp == NULL)
04688 return TRUE;
04689
04690
04691
04692
04693 MILLIPOINT SectionLength = GetLengthOfPathSection(&EditPath, FirstIndex, LastIndex);
04694 if (SectionLength == -1)
04695 return FALSE;
04696
04697 INT32 NumItems = SectionLength / MIN_BRUSH_SPACING;
04698
04699
04700 CDistanceSampler* pNewSampler = new CDistanceSampler;
04701 if (pNewSampler == NULL)
04702 return FALSE;
04703
04704 if (!pNewSampler->InitialiseData(NumItems))
04705 {
04706 delete pNewSampler;
04707 return FALSE;
04708 }
04709
04710
04711 INT32 InsertIndex = 0;
04712 if (FirstIndex != 0)
04713 InsertIndex = LastIndex;
04714
04715
04716 DocCoord* pCoord = EditPath.GetCoordArray();
04717 if (pCoord == NULL)
04718 {
04719 delete pNewSampler;
04720 return FALSE;
04721 }
04722 DocCoord InsertCoord = pCoord[InsertIndex];
04723
04724 MILLIPOINT InsertDistance = -1;
04725 if (!EditPath.GetDistanceToPoint(InsertCoord, &InsertDistance))
04726 {
04727 delete pNewSampler;
04728 return FALSE;
04729 }
04730
04731
04732 UINT32 InternalIndex = pDistSamp->GetInternalIndexFromDistance(InsertDistance);
04733
04734 if (InternalIndex == (UINT32)-1)
04735 InternalIndex = UINT32(pDistSamp->GetNumItems() - 1);
04736
04737 pDistSamp->SetRetrievalSampleRate(1.0);
04738 CSampleItem TheItem;
04739
04740 if (!pDistSamp->GetAt(InternalIndex, &TheItem))
04741 {
04742 ERROR3("Unable to retrieve pressure item in OpNodePathAddEndpoint::EditBrushAttribute");
04743 delete pNewSampler;
04744 return FALSE;
04745 }
04746
04747
04748 BOOL ok = pNewSampler->SetAt(0, TheItem);
04749 while (ok)
04750 {
04751 ok = pNewSampler->SetNext(TheItem);
04752 TRACEUSER( "Diccon", _T("Adding item pressure = %d\n"), TheItem.m_Pressure);
04753 }
04754
04755
04756 AddPressurePointsAction* pAddAction;
04757
04758
04759 size_t NumAddPoints = pNewSampler->GetNumItems() + 1;
04760
04761 if (AddPressurePointsAction::Init(this, &UndoActions, pAttrBrush, pNewSampler, InternalIndex, NumAddPoints, &pAddAction) == AC_FAIL)
04762 {
04763 delete pNewSampler;
04764 return FALSE;
04765 }
04766
04767 return TRUE;
04768 }
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787 void OpNodePathEditBlob::ChangeCursor(Cursor* cursor)
04788 {
04789 if (cursor != MyCurrentCursor)
04790 {
04791 if (MyCurrentCursor != NULL)
04792 {
04793 CursorStack::GPop(CurrentCursorID);
04794 }
04795 MyCurrentCursor = cursor;
04796 CurrentCursorID = CursorStack::GPush(cursor);
04797 }
04798 }
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816 BOOL OpNodePathEditBlob::CreateCursors()
04817 {
04818 if (pMoveCursor == NULL)
04819 {
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
04825 if ((!pMoveCursor || !pMoveCursor->IsValid())
04826 || (!pCloseCursor || !pCloseCursor->IsValid())
04827 || (!pCrossHairCursor || !pCrossHairCursor->IsValid()))
04828 {
04829
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 }
04840
04841
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857
04858 void OpNodePathEditBlob::DestroyCursors()
04859 {
04860 if (pMoveCursor != NULL)
04861 {
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 }
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893 BOOL OpNodePathEditBlob::FillPathIfEndsSnapped()
04894 {
04895
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 }
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922 BOOL OpNodePathEditBlob::FillPathIfEndsSnapped(NodePath* pOrigPath)
04923 {
04924
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 }
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966 BOOL OpNodePathAddEndpoint::InsertElement( DocCoord NewPoint,
04967 Path* DestPath,
04968 INT32 InsPos,
04969 INT32* NewPosition,
04970 BOOL RecordUndo,
04971 NodePath* UndoPath)
04972 {
04973
04974 Action* UnAction;
04975 ActionCode Act;
04976
04977
04978
04979
04980
04981
04982
04983 DestPath->SetPathPosition(InsPos);
04984
04985 if (DestPath->GetVerb() == PT_MOVETO)
04986 {
04987 DocCoord tempcoord = DestPath->GetEndPoint();
04988 DestPath->FindNext();
04989 *NewPosition = DestPath->GetPathPosition();
04990
04991
04992 if (RecordUndo)
04993 {
04994 if (AddCurveFlag)
04995 Act = RemovePathElementAction::Init(this, &UndoActions, 3,*NewPosition, (Action**)(&UnAction));
04996 else
04997 Act = RemovePathElementAction::Init(this, &UndoActions, 1,*NewPosition, (Action**)(&UnAction));
04998 if (Act == AC_FAIL)
04999 return FALSE;
05000
05001 ((RemovePathElementAction*)UnAction)->RecordPath(UndoPath);
05002 }
05003
05004 PathFlags tempflags;
05005
05006 if (AddSmoothFlag)
05007 {
05008 tempflags.IsSmooth = TRUE;
05009 tempflags.IsRotate = TRUE;
05010 }
05011 else
05012 {
05013 tempflags.IsSmooth = TRUE;
05014 tempflags.IsRotate = FALSE;
05015 }
05016
05017 if (AddCurveFlag)
05018 {
05019
05020
05021 if (!DestPath->InsertCurveTo(tempcoord,tempcoord,tempcoord,&tempflags))
05022 return FALSE;
05023 }
05024 else
05025 {
05026 if (!DestPath->InsertLineTo(tempcoord, &tempflags))
05027 return FALSE;
05028 }
05029
05030
05031 PathFlags* Flags = DestPath->GetFlagArray();
05032 DocCoord* PathCoords = DestPath->GetCoordArray();
05033 PathVerb* PathVerbs = DestPath->GetVerbArray();
05034
05035
05036 if (RecordUndo)
05037 {
05038 DoChangeSelection(UndoPath, InsPos, TRUE);
05039 if (AddCurveFlag)
05040 DoChangeSelection(UndoPath, InsPos+1, TRUE);
05041 }
05042 else
05043 {
05044 Flags[InsPos].IsSelected = TRUE;
05045 if (AddCurveFlag)
05046 Flags[InsPos+1].IsSelected = TRUE;
05047 }
05048
05049
05050
05051 if (RecordUndo)
05052 {
05053 Act = ModifyElementAction::Init(this,
05054 &UndoActions,
05055 PathVerbs[InsPos],
05056 Flags[InsPos],
05057 PathCoords[InsPos],
05058 InsPos,
05059 UndoPath,
05060 (Action**)&UnAction);
05061 }
05062
05063 PathCoords[InsPos] = NewPoint;
05064
05065
05066 Flags[InsPos].IsSmooth = TRUE;
05067 Flags[InsPos].IsRotate = TRUE;
05068
05069 DragPoint = InsPos;
05070
05071
05072
05073 }
05074 else
05075 {
05076
05077 DestPath->FindNext();
05078 *NewPosition = DestPath->GetPathPosition();
05079
05080
05081 if (RecordUndo)
05082 {
05083 if (AddCurveFlag)
05084 Act = RemovePathElementAction::Init(this, &UndoActions, 3,*NewPosition, (Action**)(&UnAction));
05085 else
05086 Act = RemovePathElementAction::Init(this, &UndoActions, 1,*NewPosition, (Action**)(&UnAction));
05087 if (Act == AC_FAIL)
05088 return FALSE;
05089
05090 ((RemovePathElementAction*)UnAction)->RecordPath(UndoPath);
05091 }
05092
05093 PathFlags tempflags;
05094 if (AddSmoothFlag)
05095 {
05096 tempflags.IsSmooth = TRUE;
05097 tempflags.IsRotate = TRUE;
05098 }
05099 else
05100 {
05101 tempflags.IsSmooth = TRUE;
05102 tempflags.IsRotate = FALSE;
05103 }
05104 if (AddCurveFlag)
05105 {
05106 if (!DestPath->InsertCurveTo(NewPoint,NewPoint,NewPoint,&tempflags))
05107 return FALSE;
05108 }
05109 else
05110 {
05111 if (!DestPath->InsertLineTo(NewPoint,&tempflags))
05112 return FALSE;
05113 }
05114
05115
05116 PathFlags* Flags = DestPath->GetFlagArray();
05117
05118
05119
05120 if (AddCurveFlag)
05121 {
05122 if (RecordUndo)
05123 {
05124 DoChangeSelection(UndoPath,(*NewPosition)+2, TRUE);
05125 DoChangeSelection(UndoPath, (*NewPosition)+1, TRUE);
05126 }
05127 else
05128 {
05129 Flags[(*NewPosition)+2].IsSelected = TRUE;
05130 Flags[(*NewPosition)+1].IsSelected = TRUE;
05131 }
05132 DragPoint = (*NewPosition)+2;
05133
05134 }
05135 else
05136 {
05137 if (RecordUndo)
05138 DoChangeSelection(UndoPath,(*NewPosition), TRUE);
05139 else
05140 Flags[(*NewPosition)].IsSelected = TRUE;
05141 DragPoint = *NewPosition;
05142 }
05143 }
05144
05145 return TRUE;
05146 }
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156 OpToggleSmooth::OpToggleSmooth()
05157 {
05158
05159 }
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171 BOOL OpToggleSmooth::Init()
05172 {
05173 return (RegisterOpDescriptor( 0,
05174 _R(IDS_NODEPATH_EDIT),
05175 CC_RUNTIME_CLASS(OpToggleSmooth),
05176 OPTOKEN_NODEPATH,
05177 OpToggleSmooth::GetState,
05178 0,
05179 _R(IDBBL_NODEPATHOP),
05180 0 ) );
05181 }
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191
05192
05193
05194
05195 OpState OpToggleSmooth::GetState(String_256* Description, OpDescriptor*)
05196 {
05197 OpState Blobby;
05198 return Blobby;
05199 }
05200
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229
05230 void OpToggleSmooth::DoTogglePoint(NodePath* ThisNode, INT32 Index, Spread* pSpread, BOOL AllSmooth, BOOL DontMoveOnCusp)
05231 {
05232 if (!DoStartSelOp(TRUE,TRUE))
05233 {
05234 FailAndExecute();
05235 End();
05236 return;
05237 }
05238
05239
05240 ObjChangeFlags cFlags;
05241 cFlags.TransformNode = TRUE;
05242 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
05243 BOOL Failed = FALSE;
05244
05245 if (ThisNode==NULL)
05246 {
05247
05248 SelRange* Selected = GetApplication()->FindSelection();
05249 Node* pNode = Selected->FindFirst();
05250 while (pNode!=NULL && !Failed)
05251 {
05252 NodePath* pSelected = pNode->IsAnEditablePath();
05253 if ( (pSelected != NULL) && (pSelected->AllowOp(&ObjChange)) )
05254 {
05255 if (!TogglePathPoints(pSelected, Index, AllSmooth, DontMoveOnCusp))
05256 {
05257 InformError();
05258 Failed = TRUE;
05259 }
05260 }
05261 pNode = Selected->FindNext(pNode);
05262 }
05263 }
05264 else
05265 {
05266 if (ThisNode->AllowOp(&ObjChange))
05267 {
05268 if (!TogglePathPoints(ThisNode, Index, AllSmooth, DontMoveOnCusp))
05269 {
05270 InformError();
05271 Failed = TRUE;
05272 }
05273 }
05274 }
05275
05276
05277 if (!Failed)
05278 {
05279 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
05280 Failed = !UpdateChangedNodes(&ObjChange);
05281 }
05282
05283 if (Failed)
05284 FailAndExecute();
05285
05286 End();
05287 }
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309
05310
05311
05312
05313
05314
05315
05316 BOOL OpToggleSmooth::TogglePathPoints(NodePath* CurrentNode, INT32 Index, BOOL AllSmooth, BOOL DontMoveOnCusp)
05317 {
05318 ERROR2IF(CurrentNode==NULL, FALSE, "Path pointer was NULL");
05319
05320 PathFlags* Flags = NULL;
05321 PathVerb* Verbs = NULL;
05322 DocCoord* Coords = NULL;
05323 CurrentNode->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
05324 ERROR2IF((Verbs==NULL) || (Coords==NULL) || (Flags==NULL), FALSE, "Path array pointer was NULL (panic!)");
05325
05326 INT32 NumCoords = CurrentNode->InkPath.GetNumCoords();
05327 INT32 LowIndex = (Index == -1) ? 0 : Index;
05328 INT32 HighIndex = (Index == -1) ? NumCoords-1 : Index;
05329
05330
05331
05332 if ( (Verbs[0] == PT_MOVETO) && (Verbs[1] == PT_BEZIERTO) && (Verbs[3] & PT_CLOSEFIGURE) &&
05333 (Coords[0] == Coords[3]) && (!Flags[0].IsRotate) )
05334 return TRUE;
05335
05336 BOOL Success = TRUE;
05337 BOOL ChangedThisPath = FALSE;
05338 for (INT32 CurrentIndex = LowIndex; (CurrentIndex <= HighIndex) && Success; CurrentIndex++)
05339 {
05340 BOOL Test = FALSE;
05341 CurrentNode->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
05342
05343 if (HighIndex != LowIndex)
05344 {
05345 if (Flags[CurrentIndex].IsEndPoint && Flags[CurrentIndex].IsSelected)
05346 {
05347 if (AllSmooth)
05348 Test = !(Flags[CurrentIndex].IsRotate);
05349 else
05350 Test = Flags[CurrentIndex].IsRotate;
05351 }
05352 else
05353 Test = FALSE;
05354 }
05355 else
05356 {
05357 Test = Flags[CurrentIndex].IsEndPoint;
05358 }
05359
05360
05361 if (Test)
05362 {
05363 ERROR3IF(!Flags[CurrentIndex].IsEndPoint, "Attempting to toggle a control point");
05364
05365
05366 if (Success && !ChangedThisPath)
05367 {
05368 Success = (RecalcBoundsAction::DoRecalc(this, &UndoActions, CurrentNode) != AC_FAIL);
05369
05370
05371
05372
05373 ChangedThisPath = TRUE;
05374 }
05375
05376
05377 if (Success)
05378 {
05379 CurrentNode->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
05380 if (Flags[CurrentIndex].IsRotate)
05381 Success = MakePointCusp(CurrentNode, CurrentIndex, DontMoveOnCusp);
05382 else
05383 Success = MakePointSmooth(CurrentNode, CurrentIndex);
05384 }
05385 }
05386 }
05387
05388
05389
05390 if (Success && ChangedThisPath)
05391 {
05392 CurrentNode->InvalidateBoundingRect();
05393 GetApplication()->FindSelection()->UpdateBounds();
05394 Success = (RecordBoundsAction::DoRecord(this, &UndoActions, CurrentNode) != AC_FAIL);
05395 }
05396
05397 return Success;
05398 }
05399
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417 BOOL OpToggleSmooth::MakePointCusp(NodePath* pPath, INT32 Index, BOOL DontMoveOnCusp)
05418 {
05419
05420 ERROR2IF(pPath == NULL, FALSE, "Path pointer was NULL");
05421 ERROR2IF(Index < 0, FALSE, "Path index was negative");
05422 ERROR2IF(Index >= pPath->InkPath.GetNumCoords(), FALSE, "Path index off end of path");
05423
05424
05425 ModifyElementAction* UnAction = NULL;
05426 PathFlags* Flags = NULL;
05427 PathVerb* Verbs = NULL;
05428 DocCoord* Coords = NULL;
05429 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
05430 ERROR2IF((Verbs==NULL) || (Coords==NULL) || (Flags==NULL), FALSE, "Path array pointer was NULL (panic!)");
05431 ActionCode Act = ModifyElementAction::Init(this, &UndoActions, Verbs[Index], Flags[Index],
05432 Coords[Index], Index, pPath, (Action**)&UnAction);
05433 if (Act == AC_FAIL)
05434 return FALSE;
05435 Flags[Index].IsSmooth = FALSE;
05436 Flags[Index].IsRotate = FALSE;
05437
05438
05439 INT32 PrevControl = pPath->InkPath.FindPrevControlPoint(Index);
05440 if (PrevControl != -1)
05441 {
05442 Act = ModifyElementAction::Init(this, &UndoActions, Verbs[PrevControl], Flags[PrevControl],
05443 Coords[PrevControl], PrevControl, pPath, (Action**)&UnAction);
05444 if (Act == AC_FAIL)
05445 return FALSE;
05446
05447
05448 if (!DontMoveOnCusp && (!((Verbs[Index] == PT_MOVETO) && (Verbs[Index+1] == PT_BEZIERTO) &&
05449 (Verbs[Index+3] & PT_CLOSEFIGURE) && (Coords[Index] == Coords[Index+3]))))
05450 {
05451 Coords[PrevControl] = DocCoord::OneThird(Coords[PrevControl+1],Coords[PrevControl-2]);
05452 }
05453 Flags[PrevControl].IsSmooth = FALSE;
05454 Flags[PrevControl].IsRotate = FALSE;
05455
05456
05457
05458
05459 if (Index != PrevControl+1)
05460 {
05461 Act = ModifyElementAction::Init(this, &UndoActions, Verbs[PrevControl+1], Flags[PrevControl+1],
05462 Coords[PrevControl+1], PrevControl+1, pPath, (Action**)&UnAction);
05463 if (Act == AC_FAIL)
05464 return FALSE;
05465 Flags[PrevControl+1].IsSmooth = FALSE;
05466 Flags[PrevControl+1].IsRotate = FALSE;
05467 }
05468 }
05469
05470
05471 INT32 NextControl = pPath->InkPath.FindNextControlPoint(Index);
05472 if (NextControl != -1)
05473 {
05474 Act = ModifyElementAction::Init(this, &UndoActions, Verbs[NextControl], Flags[NextControl],
05475 Coords[NextControl], NextControl, pPath, (Action**)&UnAction);
05476 if (Act == AC_FAIL)
05477 return FALSE;
05478
05479
05480
05481
05482 if (!DontMoveOnCusp && !((Verbs[Index] == PT_MOVETO) && (Verbs[Index+1] == PT_BEZIERTO) &&
05483 (Verbs[Index+3] & PT_CLOSEFIGURE) && (Coords[Index] == Coords[Index+3])))
05484 {
05485 Coords[NextControl] = DocCoord::OneThird(Coords[NextControl-1], Coords[NextControl+2]);
05486 }
05487 Flags[NextControl].IsSmooth = FALSE;
05488 Flags[NextControl].IsRotate = FALSE;
05489 }
05490
05491 return TRUE;
05492 }
05493
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510 BOOL OpToggleSmooth::MakePointSmooth(NodePath* pPath, INT32 Index)
05511 {
05512
05513 ERROR2IF(pPath == NULL, FALSE, "Path pointer was NULL");
05514 ERROR2IF(Index < 0, FALSE, "Path index was negative");
05515 ERROR2IF(Index >= pPath->InkPath.GetNumCoords(), FALSE, "Path index off end of path");
05516
05517
05518 ModifyElementAction* UnAction = NULL;
05519 PathFlags* Flags = NULL;
05520 PathVerb* Verbs = NULL;
05521 DocCoord* Coords = NULL;
05522 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
05523 ERROR2IF((Verbs==NULL) || (Coords==NULL) || (Flags==NULL), FALSE, "Path array pointer was NULL (panic!)");
05524 ActionCode Act = ModifyElementAction::Init(this, &UndoActions, Verbs[Index], Flags[Index],
05525 Coords[Index], Index, pPath, (Action**)&UnAction);
05526 if (Act == AC_FAIL)
05527 return FALSE;
05528 Flags[Index].IsSmooth = TRUE;
05529 Flags[Index].IsRotate = TRUE;
05530
05531
05532 INT32 PrevControl = pPath->InkPath.FindPrevControlPoint(Index);
05533 if (PrevControl != -1)
05534 {
05535 Act = ModifyElementAction::Init(this, &UndoActions, Verbs[PrevControl], Flags[PrevControl],
05536 Coords[PrevControl], PrevControl, pPath, (Action**)&UnAction);
05537 if (Act == AC_FAIL)
05538 return FALSE;
05539 Flags[PrevControl].IsSmooth = TRUE;
05540 Flags[PrevControl].IsRotate = TRUE;
05541 Coords[PrevControl] = pPath->InkPath.SmoothControlPoint(PrevControl);
05542
05543
05544
05545 if (Index != PrevControl+1)
05546 {
05547 Act = ModifyElementAction::Init(this, &UndoActions, Verbs[PrevControl+1], Flags[PrevControl+1],
05548 Coords[PrevControl+1], PrevControl+1, pPath, (Action**)&UnAction);
05549 if (Act == AC_FAIL)
05550 return FALSE;
05551 Flags[PrevControl+1].IsSmooth = TRUE;
05552 Flags[PrevControl+1].IsRotate = TRUE;
05553 }
05554 }
05555
05556
05557 INT32 NextControl = pPath->InkPath.FindNextControlPoint(Index);
05558 if (NextControl != -1)
05559 {
05560 Act = ModifyElementAction::Init(this, &UndoActions, Verbs[NextControl], Flags[NextControl],
05561 Coords[NextControl], NextControl, pPath, (Action**)&UnAction);
05562 if (Act == AC_FAIL)
05563 return FALSE;
05564 Flags[NextControl].IsSmooth = TRUE;
05565 Flags[NextControl].IsRotate = TRUE;
05566 Coords[NextControl] = pPath->InkPath.SmoothControlPoint(NextControl);
05567 }
05568
05569 return TRUE;
05570 }
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585 BOOL OpNewPath::Init()
05586 {
05587 return (RegisterOpDescriptor( 0,
05588 _R(IDS_NODEPATH_NEWPATH),
05589 CC_RUNTIME_CLASS(OpNewPath),
05590 OPTOKEN_NODEPATH,
05591 OpNewPath::GetState,
05592 0,
05593 _R(IDBBL_NODEPATHOP),
05594 0 ) );
05595 }
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612 OpState OpNewPath::GetState(String_256* Description, OpDescriptor*)
05613 {
05614 OpState Blobby;
05615
05616 return Blobby;
05617 }
05618
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644 void OpNewPath::DoStartDragEdit(DocCoord FirstPoint, DocCoord LastPoint, Spread* pSpread,
05645 ClickModifiers Mods, BOOL MakeCurve, BOOL MakeSmooth)
05646 {
05647 ConstrainPoint = FirstPoint;
05648 ConstrainPrevPoint = FirstPoint;
05649 ConstrainNextPoint = FirstPoint;
05650
05651 ERROR3IF(ConstrainPoint == DocCoord(-1,-1),"DragConstrainPoint wasn't set");
05652 if (Mods.Constrain)
05653 DocView::ConstrainToAngle(ConstrainPoint, &LastPoint);
05654 DocView::SnapCurrent(pSpread, &LastPoint);
05655
05656
05657 StartMousePos = FirstPoint;
05658 LastMousePos = LastPoint;
05659 StartSpread = pSpread;
05660 AddCurveFlag = MakeCurve;
05661 AddSmoothFlag = MakeSmooth;
05662
05663 BOOL ok = CreateCursors();
05664
05665
05666 if (ok)
05667 ok = BuildEditPath(FirstPoint, LastPoint);
05668
05669
05670 if (AddCurveFlag)
05671 UpdatePoint = 3;
05672 else
05673 UpdatePoint = 1;
05674
05675
05676 if (ok)
05677 {
05678
05679 DocRect EditPathBBox = EditPath.GetBoundingRect();
05680
05681
05682
05683 ok = StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos);
05684 }
05685
05686 if (!ok)
05687 {
05688 InformError();
05689 FailAndExecute();
05690 End();
05691 }
05692 }
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708 BOOL OpNewPath::BuildEditPath(DocCoord FirstPoint, DocCoord LastPoint)
05709 {
05710
05711 if (!EditPath.Initialise(4, 4))
05712 return FALSE;
05713
05714
05715 EditPath.InsertMoveTo(FirstPoint);
05716 if (AddCurveFlag)
05717 EditPath.InsertCurveTo(LastPoint, LastPoint, LastPoint);
05718 else
05719 EditPath.InsertLineTo(LastPoint);
05720
05721
05722 PathFlags* Flags = EditPath.GetFlagArray();
05723 INT32 NumCoords = EditPath.GetNumCoords();
05724 for (INT32 i=0;i<NumCoords;i++)
05725 {
05726 Flags[i].IsSmooth = TRUE;
05727 Flags[i].IsRotate = AddSmoothFlag;
05728 }
05729
05730
05731 if (AddCurveFlag)
05732 {
05733 Flags[2].IsSelected = Flags[3].IsSelected = TRUE;
05734 Flags[0].NeedToRender = Flags[3].NeedToRender = TRUE;
05735 }
05736 else
05737 {
05738 Flags[1].IsSelected = TRUE;
05739 Flags[0].NeedToRender = Flags[1].NeedToRender = TRUE;
05740 }
05741
05742 EditPath.SmoothCurve();
05743
05744
05745 return TRUE;
05746 }
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757
05758
05759
05760
05761
05762
05763
05764
05765
05766
05767
05768
05769
05770
05771 void OpNewPath::DragFinished(DocCoord Pos, ClickModifiers Mods, Spread* pSpread, BOOL Success, BOOL bSolidDrag)
05772 {
05773
05774 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
05775 EndDrag();
05776 DestroyCursors();
05777 BeginSlowJob();
05778
05779 BOOL ok = TRUE;
05780 NodePath* NewPath = NULL;
05781 Document* pDoc = GetWorkingDoc();
05782 ERROR3IF(pDoc == NULL, "Null Document while setting attributes for new NodePath");
05783
05784 if (Success && (pDoc != NULL))
05785 {
05786 ok = DoStartSelOp(FALSE);
05787
05788
05789 NodePath* NewPath = new NodePath;
05790 ok = (NewPath != NULL);
05791
05792
05793 if (ok)
05794 ok = NewPath->SetUpPath(24, 12);
05795
05796
05797 if (ok)
05798 ok = NewPath->InkPath.CopyPathDataFrom(&EditPath);
05799
05800
05801 if (ok)
05802 ok = pDoc->GetAttributeMgr().ApplyCurrentAttribsToNode((NodeRenderableInk*)NewPath);
05803
05804
05805 if (ok)
05806 ok = DoInsertNewNode(NewPath, pSpread, TRUE);
05807
05808
05809
05810
05811 if (ok)
05812 BROADCAST_TO_ALL(NewPathCreatedMsg(NewPath, this, &UndoActions));
05813 }
05814 else
05815 {
05816
05817 FailAndExecute();
05818 }
05819
05820
05821 if (!ok)
05822 {
05823 if (NewPath != NULL)
05824 {
05825 NewPath->CascadeDelete();
05826 delete NewPath;
05827 }
05828 FailAndExecute();
05829 }
05830
05831 End();
05832 }
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
05844
05845
05846 class JoinShapesBecomeA : public BecomeA
05847 {
05848 CC_DECLARE_MEMDUMP(JoinShapesBecomeA);
05849 public:
05850 JoinShapesBecomeA(NodePath* pThisJoinedPath) :
05851 BecomeA(BECOMEA_PASSBACK,CC_RUNTIME_CLASS(NodePath),NULL),
05852 pJoinedPath(pThisJoinedPath), pLastCreatedByNode(NULL), pLastAttrMap(NULL), pCreatedByAttrMap(NULL) {};
05853
05854 ~JoinShapesBecomeA();
05855
05856
05857 virtual BOOL PassBack(NodeRenderableInk* pNewNode,NodeRenderableInk* pCreatedByNode,CCAttrMap* pAttrMap);
05858
05859 CCAttrMap* GetLastAttrMap();
05860
05861 private:
05862 NodePath* pJoinedPath;
05863
05864 NodeRenderableInk* pLastCreatedByNode;
05865 CCAttrMap* pLastAttrMap;
05866 CCAttrMap* pCreatedByAttrMap;
05867 };
05868
05869 CC_IMPLEMENT_MEMDUMP(JoinShapesBecomeA,BecomeA);
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882
05883
05884
05885
05886
05887
05888
05889 JoinShapesBecomeA::~JoinShapesBecomeA()
05890 {
05891 if (pLastAttrMap != NULL)
05892 {
05893 pLastAttrMap->DeleteAttributes();
05894 delete pLastAttrMap;
05895 }
05896
05897 if (pCreatedByAttrMap != NULL)
05898 delete pCreatedByAttrMap;
05899 }
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921 CCAttrMap* JoinShapesBecomeA::GetLastAttrMap()
05922 {
05923 CCAttrMap* pAttrMap = pLastAttrMap;
05924
05925 if (pAttrMap == NULL)
05926 {
05927 if (pCreatedByAttrMap == NULL && pLastCreatedByNode != NULL)
05928 {
05929 pCreatedByAttrMap = new CCAttrMap(30);
05930 if (pCreatedByAttrMap != NULL)
05931 {
05932 if (!pLastCreatedByNode->FindAppliedAttributes(pCreatedByAttrMap))
05933 {
05934 delete pCreatedByAttrMap;
05935 pCreatedByAttrMap = NULL;
05936 }
05937 }
05938 }
05939
05940 pAttrMap = pCreatedByAttrMap;
05941 }
05942
05943 return pAttrMap;
05944 }
05945
05946
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963 BOOL JoinShapesBecomeA::PassBack(NodeRenderableInk* pNewNode,NodeRenderableInk* pCreatedByNode,CCAttrMap* pAttrMap)
05964 {
05965 ERROR3IF(pJoinedPath == NULL,"NULL joined path");
05966 ERROR3IF(pNewNode == NULL,"NULL new path");
05967 if (pJoinedPath == NULL || pNewNode == NULL)
05968 return TRUE;
05969
05970 if (!pNewNode->IsNodePath())
05971 {
05972 ERROR3("Received a node that's not a NodePath");
05973 return TRUE;
05974 }
05975
05976
05977 if (pLastAttrMap != NULL)
05978 {
05979 pLastAttrMap->DeleteAttributes();
05980 delete pLastAttrMap;
05981 }
05982
05983
05984 pLastCreatedByNode = pCreatedByNode;
05985 pLastAttrMap = pAttrMap;
05986
05987
05988 BOOL ok = pJoinedPath->InkPath.MergeTwoPaths(((NodePath*)pNewNode)->InkPath);
05989
05990
05991 pNewNode->CascadeDelete();
05992 delete pNewNode;
05993 pNewNode = NULL;
05994
05995 return ok;
05996 }
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009
06010
06011
06012
06013
06014
06015 OpJoinShapes::OpJoinShapes(): SelOperation()
06016 {
06017 }
06018
06019
06020
06021
06022
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06035
06036
06037 BOOL OpJoinShapes::Init()
06038 {
06039
06040 BTNOP( JOINSHAPEOP, OpJoinShapes, ARRANGE)
06041 return TRUE;
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051 }
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06064
06065
06066
06067
06068 OpState OpJoinShapes::GetState(String_256* UIDescription, OpDescriptor*)
06069 {
06070 OpState OpSt;
06071 String_256 DisableReason;
06072
06073
06074 if (Document::GetSelected() == NULL)
06075 {
06076
06077 OpSt.Greyed = TRUE;
06078
06079
06080 DisableReason = String_256(_R(IDS_NO_DOC));
06081 *UIDescription = DisableReason;
06082 return OpSt;
06083 }
06084
06085 OpSt.Greyed = FALSE;
06086
06087
06088 SelRange* Selected = GetApplication()->FindSelection();
06089 Node* pNode = Selected->FindFirst();
06090 BOOL SelectedInside = FALSE;
06091 BecomeA MyBecomeA(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath));
06092 MyBecomeA.ResetCount();
06093
06094 while (pNode != NULL)
06095 {
06096 if (pNode->CanBecomeA(&MyBecomeA))
06097 {
06098 if (pNode->FindParentOfSelected() != NULL)
06099 SelectedInside = TRUE;
06100 }
06101 pNode = Selected->FindNext(pNode);
06102 }
06103
06104
06105 if (MyBecomeA.GetCount() < 2)
06106 {
06107 OpSt.Greyed = TRUE;
06108 DisableReason = String_256(_R(IDS_JOIN_NEEDS_TWO_PATHS));
06109 *UIDescription = DisableReason;
06110 }
06111 else
06112 {
06113
06114 if (SelectedInside)
06115 {
06116 OpSt.Greyed = TRUE;
06117 DisableReason = String_256(_R(IDS_GREY_WHEN_SELECT_INSIDE));
06118 *UIDescription = DisableReason;
06119 }
06120 }
06121
06122 return(OpSt);
06123 }
06124
06125
06126
06127
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141 void OpJoinShapes::Do(OpDescriptor*)
06142 {
06143 BOOL ok = TRUE;
06144
06145
06146 if (ok)
06147 ok = DoStartSelOp(FALSE,FALSE);
06148
06149
06150 SelRange* Selected = GetApplication()->FindSelection();
06151
06152
06153 Node* pNode = Selected->FindFirst();
06154 NodePath* pJoinedPath = NULL;
06155 if (ok) (pJoinedPath = new NodePath);
06156 if (ok) ok = (pJoinedPath != NULL);
06157 if (ok) ok = pJoinedPath->SetUpPath();
06158 if (ok) ok = DoInsertNewNode(pJoinedPath,pNode,PREV,FALSE,FALSE,FALSE,FALSE);
06159
06160
06161 JoinShapesBecomeA JoinBecomeA(pJoinedPath);
06162
06163
06164 pNode = Selected->FindFirst();
06165 while (ok && (pNode != NULL))
06166 {
06167
06168 Node* pNextNode = Selected->FindNext(pNode);
06169
06170
06171 if (pNode != NULL && pNode->IsAnObject() && pNode->CanBecomeA(&JoinBecomeA))
06172 ok = ((NodeRenderableInk*)pNode)->DoBecomeA(&JoinBecomeA);
06173
06174
06175 pNode = pNextNode;
06176 }
06177
06178
06179 if (ok)
06180 {
06181 CCAttrMap* pAttrMap = JoinBecomeA.GetLastAttrMap();
06182 if (pAttrMap != NULL)
06183 pJoinedPath->ApplyAttributes(pAttrMap,TRUE);
06184 }
06185
06186
06187 pNode = Selected->FindFirst();
06188 while (ok && pNode != NULL)
06189 {
06190 Node* pNextNode = Selected->FindNext(pNode);
06191
06192 if (pNode != NULL)
06193 ok = DoHideNode(pNode,TRUE);
06194
06195
06196 pNode = pNextNode;
06197 }
06198
06199
06200 if (ok) pJoinedPath->Select(FALSE);
06201 if (ok) pJoinedPath->InvalidateBoundingRect();
06202 if (ok) ok = DoInvalidateNodeRegion(pJoinedPath,TRUE);
06203
06204
06205 if (!ok)
06206 {
06207 InformError();
06208 FailAndExecute();
06209 }
06210
06211
06212 GetApplication()->UpdateSelection();
06213
06214 End();
06215 }
06216
06217
06218
06219
06220
06221
06222
06223
06224
06225
06226
06227
06228
06229
06230
06231
06232
06233
06234
06235
06236
06237
06238
06239
06240
06241
06242
06243
06244
06245
06246
06247
06248
06249
06250
06251
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261
06262
06263
06264
06265
06266
06267
06268
06269
06270
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337 OpBreakShapes::OpBreakShapes(): SelOperation()
06338 {
06339 }
06340
06341
06342
06343
06344
06345
06346
06347
06348
06349
06350
06351
06352
06353
06354
06355
06356
06357
06358
06359 BOOL OpBreakShapes::Init()
06360 {
06361
06362 BTNOP( BREAKSHAPEOP, OpBreakShapes, ARRANGE)
06363 return TRUE;
06364
06365
06366
06367
06368
06369
06370
06371
06372
06373 }
06374
06375
06376
06377
06378
06379
06380
06381
06382
06383
06384
06385
06386
06387
06388
06389
06390 OpState OpBreakShapes::GetState(String_256* UIDescription, OpDescriptor*)
06391 {
06392 OpState OpSt;
06393 String_256 DisableReason;
06394
06395
06396 if (Document::GetSelected() == NULL)
06397 {
06398
06399 OpSt.Greyed = TRUE;
06400
06401 DisableReason = String_256(_R(IDS_NO_DOC));
06402 *UIDescription = DisableReason;
06403 return OpSt;
06404 }
06405
06406
06407 OpSt.Greyed = FALSE;
06408
06409
06410 SelRange* Selected = GetApplication()->FindSelection();
06411 Node* pNode = Selected->FindFirst();
06412
06413
06414 BOOL FoundComplex = FALSE;
06415 BOOL SelectedInside = FALSE;
06416 while (pNode)
06417 {
06418 if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodePath))
06419 {
06420
06421 FoundComplex = (((NodePath*)pNode)->InkPath.IsComplexPath());
06422
06423
06424
06425 SelectedInside = (FoundComplex && (pNode->FindParentOfSelected() != NULL));
06426
06427
06428 if (FoundComplex && !SelectedInside)
06429 break;
06430 }
06431 pNode = Selected->FindNext(pNode);
06432 }
06433
06434
06435
06436 if (!FoundComplex)
06437 {
06438 OpSt.Greyed = TRUE;
06439 DisableReason = String_256(_R(IDS_BREAK_NEEDS_COMPLEX));
06440 *UIDescription = DisableReason;
06441 }
06442 else
06443 {
06444
06445 if (SelectedInside)
06446 {
06447 OpSt.Greyed = TRUE;
06448 DisableReason = String_256(_R(IDS_GREY_WHEN_SELECT_INSIDE));
06449 *UIDescription = DisableReason;
06450 }
06451 }
06452
06453 return(OpSt);
06454 }
06455
06456
06457
06458
06459
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472 void OpBreakShapes::Do(OpDescriptor*)
06473 {
06474
06475 SelRange* Selected = GetApplication()->FindSelection();
06476
06477 NodePath* NewPath;
06478
06479
06480
06481 List* NodeList = Selected->MakeListOfNodes();
06482
06483 NodeListItem* CurItem = (NodeListItem*)(NodeList->GetHead());
06484
06485 if (!CurItem)
06486 goto FailAndDeleteList;
06487
06488 while(CurItem)
06489 {
06490 if ((CurItem->pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodePath)) &&
06491 (((NodePath*)(CurItem->pNode))->InkPath.IsComplexPath()) &&
06492 (CurItem->pNode->FindParentOfSelected() == NULL))
06493 {
06494
06495 NodePath* ThisPath = (NodePath*)(CurItem->pNode);
06496
06497
06498 INT32 SubPathIndex = 0;
06499 INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
06500
06501 while (SubPathIndex < NumCoords)
06502 {
06503
06504
06505 NewPath = new NodePath;
06506 if (!NewPath)
06507 {
06508 goto FailAndDeleteList;
06509 }
06510
06511
06512 if (!NewPath->SetUpPath(24,12))
06513 {
06514 InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
06515 goto FailAndDeleteListAndPath;
06516 }
06517
06518
06519 Node* pAttr = ThisPath->FindFirstChild();
06520 while (pAttr != NULL)
06521 {
06522 if (pAttr->IsAnAttribute())
06523 {
06524 BOOL ok;
06525 Node* pAttrCopy;
06526 CALL_WITH_FAIL(pAttr->NodeCopy(&pAttrCopy), this, ok);
06527 if (!ok)
06528 {
06529 goto FailAndDeleteListAndPath;
06530 }
06531 pAttrCopy->AttachNode(NewPath, FIRSTCHILD);
06532 }
06533 pAttr = pAttr->FindNext();
06534 }
06535
06536
06537 if (ThisPath->InkPath.IsFilled)
06538 NewPath->InkPath.IsFilled = TRUE;
06539
06540
06541
06542 INT32 EndOfSubPath = SubPathIndex;
06543 ThisPath->InkPath.FindEndOfSubPath(&EndOfSubPath);
06544
06545 ThisPath->InkPath.FindNext(&EndOfSubPath);
06546
06547
06548
06549
06550
06551 if (!(NewPath->InkPath.CopySectionFrom(ThisPath->InkPath, SubPathIndex, EndOfSubPath-SubPathIndex)))
06552 {
06553 InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
06554 goto FailAndDeleteListAndPath;
06555 }
06556
06557
06558 SubPathIndex = EndOfSubPath;
06559
06560
06561 if (!DoInsertNewNode(NewPath, ThisPath, NEXT, TRUE))
06562 {
06563 goto FailAndDeleteListAndPath;
06564 }
06565
06566
06567 }
06568
06569
06570 if (!DoHideNode(ThisPath, TRUE))
06571 goto FailAndDeleteList;
06572
06573 }
06574 CurItem = (NodeListItem*)(NodeList->GetNext(CurItem));
06575 }
06576
06577 End();
06578
06579
06580 while (!NodeList->IsEmpty())
06581 delete (NodeListItem*)(NodeList->RemoveHead());
06582 delete NodeList;
06583
06584 return;
06585
06586 FailAndDeleteListAndPath:
06587
06588 NewPath->CascadeDelete();
06589 delete NewPath;
06590
06591 FailAndDeleteList:
06592 while (!NodeList->IsEmpty())
06593 delete (NodeListItem*)(NodeList->RemoveHead());
06594 delete NodeList;
06595 FailAndExecute();
06596 End();
06597 return;
06598 }
06599
06600
06601
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613 OpDeletePoints::OpDeletePoints(): SelOperation()
06614 {
06615 }
06616
06617
06618
06619
06620
06621
06622
06623
06624
06625
06626
06627
06628
06629
06630
06631
06632 BOOL OpDeletePoints::Init()
06633 {
06634 BTNOP( DELETEPOINTSOP, OpDeletePoints, EDIT)
06635 return TRUE;
06636 }
06637
06638
06639
06640
06641
06642
06643
06644
06645
06646
06647
06648
06649
06650
06651
06652
06653
06654 OpState OpDeletePoints::GetState(String_256* UIDescription, OpDescriptor* pOpDesc)
06655 {
06656
06657 SelRange* Selected = GetApplication()->FindSelection();
06658 Node* pNode = Selected->FindFirst();
06659
06660
06661 ObjChangeParam ObjDelete(OBJCHANGE_STARTING, ObjChangeFlags(TRUE), NULL, NULL);
06662 ObjChangeParam ObjChange(OBJCHANGE_STARTING, ObjChangeFlags(), NULL, NULL);
06663
06664
06665 BOOL FoundSelected = FALSE;
06666 while (pNode != NULL)
06667 {
06668 if (IS_A(pNode, NodePath) || IS_A(pNode,NodeBlendPath))
06669 {
06670 if (((NodePath*)pNode)->InkPath.IsSubSelection())
06671 {
06672
06673 BOOL WillHide = WillDeleteEntirePath((NodePath*)pNode);
06674
06675
06676 BOOL Result = FALSE;
06677 if (WillHide)
06678 Result = pNode->AllowOp(&ObjDelete, FALSE);
06679 else
06680 Result = pNode->AllowOp(&ObjChange, FALSE);
06681
06682 if (Result)
06683 {
06684
06685 FoundSelected = TRUE;
06686 break;
06687 }
06688 }
06689
06690 }
06691 pNode = Selected->FindNext(pNode);
06692 }
06693
06694 OpState OpSt;
06695
06696 if (!FoundSelected)
06697 {
06698 OpSt.Greyed = TRUE;
06699 *UIDescription = String_256(_R(IDS_NEEDS_SELECTED_POINT));
06700 }
06701
06702 return(OpSt);
06703 }
06704
06705
06706
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720 void OpDeletePoints::Do(OpDescriptor*)
06721 {
06722
06723 SelRange* Selected = GetApplication()->FindSelection();
06724 Node* pNode = Selected->FindFirst();
06725
06726 BOOL ok = DoStartSelOp(TRUE,TRUE);
06727
06728
06729 ObjChangeFlags cFlags;
06730 cFlags.TransformNode = TRUE;
06731 ObjChangeParam ObjDelete(OBJCHANGE_STARTING,ObjChangeFlags(TRUE),NULL,this);
06732 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
06733
06734
06735 while (pNode != NULL)
06736 {
06737
06738 Node* NextNode = Selected->FindNext(pNode);
06739
06740
06741
06742 BOOL DoThisPath = (IS_A(pNode, NodePath) || IS_A(pNode,NodeBlendPath)) && ((NodePath*)pNode)->InkPath.IsSubSelection();
06743
06744
06745 BOOL WillDelete = FALSE;
06746 if (DoThisPath)
06747 {
06748 WillDelete = WillDeleteEntirePath((NodePath*)pNode);
06749 if (WillDelete)
06750 DoThisPath = pNode->AllowOp(&ObjDelete);
06751 else
06752 DoThisPath = pNode->AllowOp(&ObjChange);
06753 }
06754
06755
06756 if (DoThisPath && ok)
06757 {
06758 NodePath* ThisPath = (NodePath*)pNode;
06759 INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
06760 PathVerb* Verbs = NULL;
06761 PathFlags* Flags = NULL;
06762 DocCoord* Coords = NULL;
06763 ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
06764 BOOL PathStillExists = TRUE;
06765
06766
06767 ok = RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath) != AC_FAIL ;
06768
06769
06770
06771
06772
06773
06774 if (WillDelete)
06775 {
06776 if (ok)
06777 ok = DoHideNode(pNode, TRUE);
06778 PathStillExists = FALSE;
06779 }
06780
06781
06782 while (ok && PathStillExists && ThisPath->InkPath.IsSubSelection())
06783 {
06784
06785 ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
06786 NumCoords = ThisPath->InkPath.GetNumCoords();
06787
06788
06789 INT32 i;
06790 for ( i =0;i<NumCoords && (!Flags[i].IsSelected || !Flags[i].IsEndPoint);i++)
06791 ;
06792
06793
06794
06795
06796 if (i == NumCoords)
06797 {
06798 for (i=0;i<NumCoords;i++)
06799 {
06800 ok = ok && DoChangeSelection(ThisPath, i,FALSE);
06801 }
06802 }
06803 else
06804 {
06805
06806
06807 switch (Verbs[i] & ~PT_CLOSEFIGURE)
06808 {
06809 case PT_LINETO:
06810 ok = DeleteLineTo(ThisPath, i, &PathStillExists);
06811 break;
06812 case PT_BEZIERTO:
06813 ok = DeleteBezierTo(ThisPath, i, &PathStillExists);
06814 break;
06815 case PT_MOVETO:
06816 ok = DeleteMoveTo(ThisPath, i, &PathStillExists);
06817 break;
06818 }
06819 }
06820 }
06821
06822
06823
06824
06825 if (ok && PathStillExists && !ThisPath->IsPathAllowable())
06826 {
06827 if (ok)
06828 ok = DoInvalidateNodeRegion(ThisPath,TRUE,TRUE);
06829 if (ok)
06830 ok = DoHideNode(ThisPath, TRUE);
06831 PathStillExists = FALSE;
06832 }
06833
06834
06835
06836 if (PathStillExists && ok)
06837 {
06838 ThisPath->InvalidateBoundingRect();
06839 ok = RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath) != AC_FAIL;
06840 }
06841 }
06842 pNode = NextNode;
06843 }
06844
06845
06846 if (ok)
06847 {
06848 ObjChange.Define(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,this);
06849 ok = UpdateChangedNodes(&ObjChange);
06850 }
06851
06852 if (!ok)
06853 {
06854 InformError();
06855 FailAndExecute();
06856 }
06857
06858 GetApplication()->UpdateSelection();
06859
06860 End();
06861 }
06862
06863
06864
06865
06866
06867
06868
06869
06870
06871
06872
06873
06874
06875
06876
06877
06878
06879
06880
06881
06882 BOOL OpDeletePoints::DeleteLineTo(NodePath* pPath, INT32 Index, BOOL* PathExists)
06883 {
06884 PathVerb* Verbs = pPath->InkPath.GetVerbArray();
06885 PathFlags* Flags = pPath->InkPath.GetFlagArray();
06886 DocCoord* Coords = pPath->InkPath.GetCoordArray();
06887 INT32 NumCoords = pPath->InkPath.GetNumCoords();
06888 PathVerb TempVerb;
06889 PathFlags TempFlags;
06890 DocCoord EndPoint;
06891
06892
06893 if (Index+1 != NumCoords)
06894 {
06895
06896 switch (Verbs[Index+1] & ~PT_CLOSEFIGURE)
06897 {
06898 case PT_LINETO:
06899 return DoDeletePathSection(pPath, Index, 1) ;
06900 break;
06901 case PT_BEZIERTO:
06902
06903
06904 EndPoint = Coords[Index+3];
06905 TempVerb = Verbs[Index];
06906 TempFlags = Flags[Index];
06907 TempFlags.IsSelected = Flags[Index+3].IsSelected;
06908
06909
06910
06911
06912 return (DoAlterPathElement(pPath, Index, EndPoint, TempFlags, TempVerb)
06913 && DoDeletePathSection(pPath, Index+1, 3));
06914 break;
06915 case PT_MOVETO:
06916
06917
06918 if (Verbs[Index] & PT_CLOSEFIGURE)
06919 {
06920
06921
06922
06923 return DoChangeSelection(pPath, Index, FALSE) ;
06924 }
06925 else
06926 {
06927
06928
06929 if (Verbs[Index-1] == PT_MOVETO)
06930 return DoDeletePathSection(pPath, Index-1, 2);
06931 else
06932 return DoDeletePathSection(pPath, Index, 1);
06933 }
06934 break;
06935 default :
06936 ERROR2(FALSE, "Corrupted path found in DeleteLineTo");
06937 }
06938 }
06939 else
06940 {
06941
06942
06943 if (Verbs[Index] & PT_CLOSEFIGURE)
06944 {
06945
06946
06947
06948
06949 return DoChangeSelection(pPath, Index, FALSE);
06950 }
06951 else
06952 {
06953
06954
06955 if (Verbs[Index-1] == PT_MOVETO)
06956 {
06957
06958
06959
06960 if (NumCoords == 2)
06961 {
06962
06963 *PathExists = FALSE;
06964 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE)) ;
06965 }
06966 else
06967 {
06968
06969 return DoDeletePathSection(pPath, Index-1, 2);
06970 }
06971 }
06972 else
06973 {
06974
06975 return DoDeletePathSection(pPath, Index, 1);
06976 }
06977 }
06978 }
06979 }
06980
06981
06982
06983
06984
06985
06986
06987
06988
06989
06990
06991
06992
06993
06994
06995
06996
06997
06998
06999
07000 BOOL OpDeletePoints::DeleteMoveTo(NodePath* pPath, INT32 Index, BOOL* PathExists)
07001 {
07002 PathVerb* Verbs = pPath->InkPath.GetVerbArray();
07003 PathFlags* Flags = pPath->InkPath.GetFlagArray();
07004 DocCoord* Coords = pPath->InkPath.GetCoordArray();
07005 INT32 NumCoords = pPath->InkPath.GetNumCoords();
07006 PathFlags TempFlags;
07007 DocCoord EndPoint;
07008
07009
07010
07011 if (pPath->InkPath.IsSubPathClosed(Index))
07012 {
07013
07014
07015
07016 if (!DoChangeSelection(pPath, Index, FALSE))
07017 return FALSE;
07018
07019
07020
07021
07022
07023
07024
07025
07026 INT32 EndIndex = Index;
07027 pPath->InkPath.FindEndOfSubPath(&EndIndex);
07028
07029
07030
07031
07032 INT32 SubPathElements = EndIndex - Index;
07033 if (Verbs[EndIndex] == PT_BEZIERTO)
07034 SubPathElements += 2;
07035
07036 if (((SubPathElements == 1) && (Flags[Index+1].IsSelected) ) ||
07037 ((SubPathElements == 3) && (Flags[Index+3].IsSelected) && ((Verbs[Index+3] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) ) )
07038 {
07039 if (SubPathElements == 1)
07040 {
07041 return (DoChangeSelection(pPath, Index+1, FALSE) &&
07042 DoDeletePathSection(pPath, Index, 2) );
07043 }
07044 else
07045 {
07046 return (DoChangeSelection(pPath, Index+3, FALSE) &&
07047 DoDeletePathSection(pPath, Index, 4) );
07048 }
07049 }
07050
07051
07052
07053
07054
07055
07056
07057 PathVerb StartVerb = Verbs[Index+1] & ~PT_CLOSEFIGURE;
07058 PathVerb EndVerb = Verbs[EndIndex] & ~PT_CLOSEFIGURE;
07059
07060 if ( StartVerb == PT_BEZIERTO && EndVerb == PT_BEZIERTO )
07061 {
07062
07063
07064
07065
07066 if ( ! (DoAlterPathElement(pPath, EndIndex+1, Coords[Index+2], Flags[Index+2], Verbs[Index+2]) &&
07067
07068 DoAlterPathElement(pPath, EndIndex+2, Coords[Index+3], Flags[Index+3], Verbs[EndIndex+2]) &&
07069
07070 DoAlterPathElement(pPath, Index, Coords[Index+3], Flags[Index], Verbs[Index]) &&
07071
07072 DoDeletePathSection(pPath, Index+1, 3)
07073 ) )
07074 {
07075 return FALSE;
07076 }
07077
07078 }
07079 else if (StartVerb == PT_LINETO && EndVerb == PT_BEZIERTO)
07080 {
07081
07082
07083
07084
07085 if ( ! (DoAlterPathElement(pPath, Index, Coords[EndIndex-1], Flags[Index], Verbs[Index]) &&
07086
07087 DoAlterPathElement(pPath, EndIndex-1, Coords[EndIndex-1], Flags[EndIndex-1], Verbs[EndIndex-1] | PT_CLOSEFIGURE) &&
07088
07089 DoDeletePathSection(pPath, EndIndex, 3)
07090 ) )
07091 {
07092 return FALSE;
07093 }
07094 }
07095 else if (StartVerb == PT_BEZIERTO && EndVerb == PT_LINETO)
07096 {
07097
07098
07099
07100
07101 if ( ! (DoChangeSelection(pPath, EndIndex, Flags[Index+3].IsSelected) &&
07102 DoAlterPathElement(pPath, EndIndex, Coords[Index+3], Flags[EndIndex], Verbs[EndIndex]) &&
07103 DoAlterPathElement(pPath, Index, Coords[Index+3], Flags[Index], Verbs[Index]) &&
07104
07105 DoDeletePathSection(pPath, Index+1, 3)
07106 ) )
07107 {
07108 return FALSE;
07109 }
07110 }
07111 else
07112 {
07113
07114
07115
07116 if ( ! (DoAlterPathElement(pPath, Index, Coords[Index+1], Flags[Index], Verbs[Index]) &&
07117 DoAlterPathElement(pPath, EndIndex, Coords[Index+1], Flags[EndIndex], Verbs[EndIndex]) &&
07118
07119 DoChangeSelection(pPath, EndIndex, Flags[Index+1].IsSelected) &&
07120
07121 DoDeletePathSection(pPath, Index+1, 1)
07122 ) )
07123 {
07124 return FALSE;
07125 }
07126 }
07127
07128
07129 Coords = pPath->InkPath.GetCoordArray();
07130 Verbs = pPath->InkPath.GetVerbArray();
07131 Flags = pPath->InkPath.GetFlagArray();
07132
07133
07134
07135
07136 EndIndex = Index;
07137 pPath->InkPath.FindEndOfSubPath(&EndIndex);
07138 BOOL IsSelected;
07139 if ((Verbs[EndIndex] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
07140 IsSelected = Flags[EndIndex+2].IsSelected;
07141 else
07142 IsSelected = Flags[EndIndex].IsSelected;
07143
07144
07145
07146 return DoChangeSelection(pPath, Index, IsSelected);
07147 }
07148 else
07149 {
07150
07151
07152 if ((Verbs[Index+1] & ~ PT_CLOSEFIGURE) == PT_BEZIERTO)
07153 {
07154
07155 if (Index+4 == NumCoords || Verbs[Index+4] == PT_MOVETO)
07156 {
07157
07158 if (NumCoords == 4)
07159 {
07160
07161 *PathExists = FALSE;
07162 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE)) ;
07163 }
07164 else
07165 {
07166 return DoDeletePathSection(pPath, Index, 4);
07167 }
07168 }
07169 else
07170 {
07171
07172
07173 EndPoint = Coords[Index+3];
07174
07175
07176
07177 BOOL WasSelected = Flags[Index+3].IsSelected;
07178
07179
07180 PathFlags TempFlags = Flags[Index];
07181 TempFlags.IsSelected = WasSelected;
07182 PathVerb TempVerb = Verbs[Index];
07183 if (!DoDeletePathSection(pPath, Index+1, 3))
07184 return FALSE;
07185
07186
07187 return DoAlterPathElement(pPath, Index, EndPoint, TempFlags, TempVerb);
07188 }
07189 }
07190 else
07191 {
07192
07193
07194 ERROR2IF(((Verbs[Index+1] & ~PT_CLOSEFIGURE) != PT_LINETO), FALSE, "Badly formed path in DeletePoint");
07195
07196
07197 if (Index+2 == NumCoords || Verbs[Index+2] == PT_MOVETO)
07198 {
07199
07200
07201 if (NumCoords == 2)
07202 {
07203
07204 *PathExists = FALSE;
07205 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE)) ;
07206 }
07207 else
07208 {
07209
07210 return DoDeletePathSection(pPath, Index, 2);
07211 }
07212 }
07213 else
07214 {
07215
07216
07217
07218 EndPoint = Coords[Index+1];
07219
07220
07221 BOOL WasSelected = Flags[Index+1].IsSelected;
07222
07223
07224 PathFlags TempFlags = Flags[Index];
07225 TempFlags.IsSelected = WasSelected;
07226 PathVerb TempVerb = Verbs[Index];
07227 if (!DoDeletePathSection(pPath, Index+1, 1))
07228 return FALSE;
07229
07230
07231
07232 return DoAlterPathElement(pPath, Index, EndPoint, TempFlags, TempVerb);
07233 }
07234 }
07235 }
07236 }
07237
07238
07239
07240
07241
07242
07243
07244
07245
07246
07247
07248
07249
07250
07251
07252
07253
07254
07255 BOOL OpDeletePoints::DeleteBezierTo(NodePath* pPath, INT32 Index, BOOL* PathExists)
07256 {
07257 PathVerb* Verbs = pPath->InkPath.GetVerbArray();
07258
07259
07260 INT32 NumCoords = pPath->InkPath.GetNumCoords();
07261 PathFlags TempFlags;
07262 DocCoord EndPoint;
07263
07264
07265 if (Index+1 != NumCoords)
07266 {
07267
07268 switch (Verbs[Index+1] & ~ PT_CLOSEFIGURE)
07269 {
07270 case PT_LINETO:
07271
07272 return DoDeletePathSection(pPath, Index-2, 3);
07273 break;
07274 case PT_BEZIERTO:
07275
07276
07277
07278 return DoDeletePathSection(pPath, Index-1, 3);
07279 break;
07280 case PT_MOVETO:
07281
07282
07283 if (Verbs[Index] & PT_CLOSEFIGURE)
07284 {
07285
07286
07287 return DoChangeSelection(pPath, Index, FALSE);
07288 }
07289 else
07290 {
07291
07292
07293
07294 if (Verbs[Index-3] == PT_MOVETO)
07295 {
07296
07297 return DoDeletePathSection(pPath, Index-3, 4);
07298 }
07299 else
07300 {
07301
07302 return DoDeletePathSection(pPath, Index-2, 3);
07303 }
07304 }
07305 break;
07306 default:
07307 ERROR2(FALSE,"Corrupt path found in DeleteBezierTo");
07308 }
07309 }
07310 else
07311 {
07312
07313
07314 if (Verbs[Index] & PT_CLOSEFIGURE)
07315 {
07316
07317
07318 return DoChangeSelection(pPath, Index, FALSE);
07319 }
07320 else
07321 {
07322
07323
07324 if (Verbs[Index-3] == PT_MOVETO)
07325 {
07326
07327 if (NumCoords == 4)
07328 {
07329
07330
07331 *PathExists = FALSE;
07332 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE));
07333 }
07334 else
07335 {
07336
07337 return DoDeletePathSection(pPath, Index-3, 4);
07338 }
07339 }
07340 else
07341 {
07342
07343 return DoDeletePathSection(pPath, Index-2, 3);
07344 }
07345 }
07346 }
07347 }
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364 BOOL OpDeletePoints::WillDeleteEntirePath(NodePath* pTreePath)
07365 {
07366
07367 if (!pTreePath->InkPath.IsSubSelection())
07368 return FALSE;
07369
07370
07371 INT32 NumCoords = pTreePath->InkPath.GetNumCoords();
07372 PathVerb* Verbs = NULL;
07373 DocCoord* Coords = NULL;
07374 PathFlags* Flags = NULL;
07375 pTreePath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
07376 BOOL PathStillExists = TRUE;
07377
07378
07379
07380 INT32 loop = 0;
07381 BOOL Selected = TRUE;
07382 while (Selected && (loop < NumCoords))
07383 {
07384 if (Flags[loop].IsEndPoint && !Flags[loop].IsSelected)
07385 Selected = FALSE;
07386 loop++;
07387 }
07388 if (Selected)
07389 return TRUE;
07390
07391
07392 NodePath* pPath = (NodePath*)pTreePath->SimpleCopy();
07393 if (pPath == NULL)
07394 return FALSE;
07395
07396
07397 while (PathStillExists)
07398 {
07399
07400 NumCoords = pPath->InkPath.GetNumCoords();
07401 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
07402
07403
07404 INT32 i;
07405 for ( i =0;i<NumCoords && (!Flags[i].IsSelected || !Flags[i].IsEndPoint);i++)
07406 ;
07407
07408
07409 if (i == NumCoords)
07410 break;
07411
07412
07413 switch (Verbs[i] & ~PT_CLOSEFIGURE)
07414 {
07415 case PT_LINETO:
07416 TryDeleteLineTo(pPath, i, &PathStillExists);
07417 break;
07418 case PT_BEZIERTO:
07419 TryDeleteBezierTo(pPath, i, &PathStillExists);
07420 break;
07421 case PT_MOVETO:
07422 TryDeleteMoveTo(pPath, i, &PathStillExists);
07423 break;
07424 default:
07425 ERROR3("What was that path verb?");
07426 }
07427 }
07428
07429
07430
07431 if (PathStillExists)
07432 PathStillExists = pPath->IsPathAllowable();
07433
07434 delete pPath;
07435
07436 return !PathStillExists;
07437 }
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
07451
07452
07453
07454
07455
07456 BOOL OpDeletePoints::TryDeleteLineTo(NodePath* pPath, INT32 Index, BOOL* PathExists)
07457 {
07458
07459 INT32 NumCoords = pPath->InkPath.GetNumCoords();
07460 PathVerb* Verbs = NULL;
07461 DocCoord* Coords = NULL;
07462 PathFlags* Flags = NULL;
07463 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
07464
07465
07466 if (Index+1 != NumCoords)
07467 {
07468
07469 switch (Verbs[Index+1] & ~PT_CLOSEFIGURE)
07470 {
07471 case PT_LINETO:
07472
07473 return (pPath->InkPath.DeleteSection(Index, 1));
07474 break;
07475 case PT_BEZIERTO:
07476
07477 Flags[Index].IsSelected = Flags[Index+3].IsSelected;
07478 Coords[Index] = Coords[Index+3];
07479 return pPath->InkPath.DeleteSection(Index+1, 3);
07480 break;
07481 case PT_MOVETO:
07482
07483 if (Verbs[Index] & PT_CLOSEFIGURE)
07484 {
07485
07486 Flags[Index].IsSelected = FALSE;
07487 return TRUE;
07488 }
07489 else
07490 {
07491
07492
07493 if (Verbs[Index-1] == PT_MOVETO)
07494 return (pPath->InkPath.DeleteSection(Index-1, 2));
07495 else
07496 return (pPath->InkPath.DeleteSection(Index, 1));
07497 }
07498 break;
07499 default :
07500 ERROR2(FALSE, "Corrupted path found in DeleteLineTo");
07501 }
07502 }
07503 else
07504 {
07505
07506
07507 if (Verbs[Index] & PT_CLOSEFIGURE)
07508 {
07509
07510 Flags[Index].IsSelected = FALSE;
07511 return TRUE;
07512 }
07513 else
07514 {
07515 if (Verbs[Index-1] == PT_MOVETO)
07516 {
07517 if (NumCoords == 2)
07518 {
07519
07520 *PathExists = FALSE;
07521 return TRUE;
07522 }
07523 else
07524 {
07525
07526 return (pPath->InkPath.DeleteSection(Index-1, 2));
07527 }
07528 }
07529 else
07530 {
07531
07532 return (pPath->InkPath.DeleteSection(Index, 1));
07533 }
07534 }
07535 }
07536 }
07537
07538
07539
07540
07541
07542
07543
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553
07554 BOOL OpDeletePoints::TryDeleteMoveTo(NodePath* pPath, INT32 Index, BOOL* PathExists)
07555 {
07556
07557 INT32 NumCoords = pPath->InkPath.GetNumCoords();
07558 PathVerb* Verbs = NULL;
07559 DocCoord* Coords = NULL;
07560 PathFlags* Flags = NULL;
07561 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
07562
07563
07564 if (pPath->InkPath.IsSubPathClosed(Index))
07565 {
07566
07567 Flags[Index].IsSelected = FALSE;
07568
07569
07570 INT32 EndIndex = Index;
07571 pPath->InkPath.FindEndOfSubPath(&EndIndex);
07572
07573
07574
07575
07576 INT32 SubPathElements = EndIndex - Index;
07577 if (Verbs[EndIndex] == PT_BEZIERTO)
07578 SubPathElements += 2;
07579
07580 if (((SubPathElements == 1) && (Flags[Index+1].IsSelected) ) ||
07581 ((SubPathElements == 3) && (Flags[Index+3].IsSelected) && ((Verbs[Index+3] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) ) )
07582 {
07583 if (SubPathElements == 1)
07584 {
07585 Flags[Index+1].IsSelected = FALSE;
07586 return (pPath->InkPath.DeleteSection(Index, 2));
07587 }
07588 else
07589 {
07590 Flags[Index+3].IsSelected = FALSE;
07591 return (pPath->InkPath.DeleteSection(Index, 4));
07592 }
07593 }
07594
07595
07596 PathVerb StartVerb = Verbs[Index+1] & ~PT_CLOSEFIGURE;
07597 PathVerb EndVerb = Verbs[EndIndex] & ~PT_CLOSEFIGURE;
07598
07599 if ( StartVerb == PT_BEZIERTO && EndVerb == PT_BEZIERTO )
07600 {
07601
07602
07603
07604
07605 Coords[EndIndex+1] = Coords[Index+2];
07606 Flags[EndIndex+1] = Flags[Index+2];
07607 Verbs[EndIndex+1] = Verbs[Index+2];
07608
07609 Coords[EndIndex+2] = Coords[Index+3];
07610 Flags[EndIndex+2] = Flags[Index+3];
07611
07612 Coords[Index] = Coords[Index+3];
07613
07614 return pPath->InkPath.DeleteSection(Index+1, 3);
07615 }
07616 else if (StartVerb == PT_LINETO && EndVerb == PT_BEZIERTO)
07617 {
07618
07619
07620
07621
07622 Coords[Index] = Coords[EndIndex-1];
07623
07624 Verbs[EndIndex-1] = Verbs[EndIndex-1] | PT_CLOSEFIGURE;
07625
07626 Coords[Index] = Coords[Index+3];
07627
07628 return pPath->InkPath.DeleteSection(EndIndex, 3);
07629 }
07630 else if (StartVerb == PT_BEZIERTO && EndVerb == PT_LINETO)
07631 {
07632
07633
07634
07635
07636 Flags[EndIndex].IsSelected = Flags[Index+3].IsSelected;
07637
07638 Coords[EndIndex] = Coords[Index+3];
07639
07640 Coords[Index] = Coords[Index+3];
07641
07642 return pPath->InkPath.DeleteSection(Index+1, 3);
07643 }
07644 else
07645 {
07646
07647
07648
07649 Coords[Index] = Coords[Index+1];
07650
07651 Coords[EndIndex] = Coords[Index+1];
07652
07653 Flags[EndIndex].IsSelected = Flags[Index+1].IsSelected;
07654
07655 return pPath->InkPath.DeleteSection(Index+1, 1);
07656 }
07657
07658
07659 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
07660
07661
07662
07663
07664 EndIndex = Index;
07665 pPath->InkPath.FindEndOfSubPath(&EndIndex);
07666 BOOL IsSelected;
07667 if ((Verbs[EndIndex] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
07668 IsSelected = Flags[EndIndex+2].IsSelected;
07669 else
07670 IsSelected = Flags[EndIndex].IsSelected;
07671
07672
07673
07674 Flags[Index].IsSelected = IsSelected;
07675 }
07676 else
07677 {
07678
07679
07680 if ((Verbs[Index+1] & ~ PT_CLOSEFIGURE) == PT_BEZIERTO)
07681 {
07682
07683 if (Index+4 == NumCoords || Verbs[Index+4] == PT_MOVETO)
07684 {
07685
07686 if (NumCoords == 4)
07687 {
07688 *PathExists = FALSE;
07689 return TRUE;
07690 }
07691 else
07692 return pPath->InkPath.DeleteSection(Index, 4);
07693 }
07694 else
07695 {
07696 Coords[Index] = Coords[Index+3];
07697 Flags[Index].IsSelected = Flags[Index+3].IsSelected;
07698
07699 return pPath->InkPath.DeleteSection(Index+1, 3);
07700 }
07701 }
07702 else
07703 {
07704
07705
07706 ERROR2IF(((Verbs[Index+1] & ~PT_CLOSEFIGURE) != PT_LINETO), FALSE, "Badly formed path in DeletePoint");
07707
07708
07709 if (Index+2 == NumCoords || Verbs[Index+2] == PT_MOVETO)
07710 {
07711
07712
07713 if (NumCoords == 2)
07714 {
07715 *PathExists = FALSE;
07716 return TRUE;
07717 }
07718 else
07719 return pPath->InkPath.DeleteSection(Index, 2);
07720 }
07721 else
07722 {
07723
07724
07725
07726 Coords[Index] = Coords[Index+1];
07727 Flags[Index].IsSelected = Flags[Index+1].IsSelected;
07728
07729 return pPath->InkPath.DeleteSection(Index+1, 1);
07730 }
07731 }
07732 }
07733 }
07734
07735
07736
07737
07738
07739
07740
07741
07742
07743
07744
07745
07746
07747
07748
07749
07750
07751
07752 BOOL OpDeletePoints::TryDeleteBezierTo(NodePath* pPath, INT32 Index, BOOL* PathExists)
07753 {
07754 PathVerb* Verbs = pPath->InkPath.GetVerbArray();
07755 PathFlags* Flags = pPath->InkPath.GetFlagArray();
07756
07757 INT32 NumCoords = pPath->InkPath.GetNumCoords();
07758 PathFlags TempFlags;
07759 DocCoord EndPoint;
07760
07761
07762 if (Index+1 != NumCoords)
07763 {
07764
07765 switch (Verbs[Index+1] & ~PT_CLOSEFIGURE)
07766 {
07767 case PT_LINETO:
07768
07769 return pPath->InkPath.DeleteSection(Index-2, 3);
07770 break;
07771 case PT_BEZIERTO:
07772
07773
07774 return pPath->InkPath.DeleteSection(Index-1, 3);
07775 break;
07776 case PT_MOVETO:
07777
07778
07779 if (Verbs[Index] & PT_CLOSEFIGURE)
07780 {
07781
07782 Flags[Index].IsSelected = FALSE;
07783 return TRUE;
07784 }
07785 else
07786 {
07787
07788
07789
07790 if (Verbs[Index-3] == PT_MOVETO)
07791 {
07792
07793 return pPath->InkPath.DeleteSection(Index-3, 4);
07794 }
07795 else
07796 {
07797
07798 return pPath->InkPath.DeleteSection(Index-2, 3);
07799 }
07800 }
07801 break;
07802 default:
07803 ERROR2(FALSE,"Corrupt path found in DeleteBezierTo");
07804 }
07805 }
07806 else
07807 {
07808
07809 if (Verbs[Index] & PT_CLOSEFIGURE)
07810 {
07811
07812 Flags[Index].IsSelected = FALSE;
07813 return TRUE;
07814 }
07815 else
07816 {
07817
07818 if (Verbs[Index-3] == PT_MOVETO)
07819 {
07820
07821 if (NumCoords == 4)
07822 {
07823 *PathExists = FALSE;
07824 return TRUE;
07825 }
07826 else
07827 {
07828
07829 return pPath->InkPath.DeleteSection(Index-3, 4);
07830 }
07831 }
07832 else
07833 {
07834
07835 return pPath->InkPath.DeleteSection(Index-2, 3);
07836 }
07837 }
07838 }
07839 }
07840
07841
07842
07844
07845
07846
07847
07848
07849
07850
07851
07852
07853
07854
07855
07856
07857
07858
07859
07860
07861
07862
07863
07864
07865
07866
07867
07868
07869 void OpReshapeOrAddPoint::DoStartDragEdit(NodePath* OrigPath, DocCoord Anchor,
07870 Spread *pSpread, INT32 SegmentIndex, double pdist)
07871 {
07872
07873 LastMousePos = Anchor;
07874 StartMousePos = Anchor;
07875 FurthestPoint = Anchor;
07876 StartSpread = pSpread;
07877 OriginalPath = OrigPath;
07878 Index = SegmentIndex;
07879 paramdist = pdist;
07880
07881 CreateCursors();
07882
07883
07884 if (!BuildEditPath())
07885 {
07886
07887 TRACEUSER( "Jim", _T("Failed to get the mem to copy the path data for editing\n") );
07888
07889
07890 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
07891 End();
07892 return;
07893 }
07894
07895
07896 DocRect EditPathBBox = EditPath.GetBoundingRect();
07897 RenderPathEditBlobs(EditPathBBox, pSpread);
07898
07899
07900 DocCoord* Coords = EditPath.GetCoordArray();
07901 PathVerb* Verbs = EditPath.GetVerbArray();
07902 if (Verbs[Index] == PT_BEZIERTO)
07903 {
07904 OrigControl1 = Coords[Index];
07905 OrigControl2 = Coords[Index+1];
07906 }
07907 else
07908 {
07909 ERROR3("Control Point wasn't a control point!");
07910 }
07911
07912
07913 StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos);
07914
07915 SetStatusLineHelp();
07916 }
07917
07918
07919
07920
07921
07922
07923
07924
07925
07926
07927
07928
07929
07930
07931
07932
07933
07934
07935 void OpReshapeOrAddPoint::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, Spread *pSpread, BOOL bSolidDrag)
07936 {
07937 EndSnapped = FALSE;
07938
07939
07940
07941 if (pSpread != StartSpread)
07942 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
07943
07944
07945 DocView::SnapCurrent(StartSpread,&PointerPos);
07946
07947
07948 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
07949
07950
07951
07952 DocCoord Offset;
07953 Offset.x = PointerPos.x - StartMousePos.x;
07954 Offset.y = PointerPos.y - StartMousePos.y;
07955 RecalculatePath( Offset );
07956
07957
07958 if (PointerPos.Distance(StartMousePos) > FurthestPoint.Distance(StartMousePos))
07959 {
07960 FurthestPoint.x = PointerPos.x;
07961 FurthestPoint.y = PointerPos.y;
07962 }
07963
07964
07965 LastMousePos = PointerPos;
07966 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
07967
07968 SetStatusLineHelp();
07969 }
07970
07971
07972
07973
07974
07975
07976
07977
07978
07979
07980
07981
07982
07983
07984
07985
07986
07987 void OpReshapeOrAddPoint::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods,
07988 Spread* pSpread, BOOL Success, BOOL bSolidDrag)
07989 {
07990 RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
07991 EndDrag();
07992 DestroyCursors();
07993 BeginSlowJob();
07994
07995 BOOL Worked = TRUE;
07996
07997 if ( Success )
07998 {
07999 ObjChangeFlags cFlags;
08000 cFlags.TransformNode = TRUE;
08001 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,OriginalPath,this);
08002
08003 Worked = DoStartSelOp(TRUE,TRUE) ;
08004
08005
08006 if (Worked)
08007 {
08008 Worked = OriginalPath->AllowOp(&ObjChange) ;
08009 }
08010
08011
08012 if (Worked)
08013 {
08014
08015
08016
08017
08018
08019
08020
08021 if (StartMousePos == FurthestPoint)
08022 {
08023 Worked = DragFinishedAddPoint();
08024 }
08025 else
08026 {
08027 BOOL Optimise = CopyNeedToRenderFlags() && !(EndSnapped || SnapToAnother);
08028
08029
08030
08031
08032
08033
08034
08035
08036 if (!IS_A(OriginalPath,NodePath))
08037 Optimise = FALSE;
08038
08039
08040 if (RecalcBoundsAction::DoRecalc(this, &UndoActions, OriginalPath, Optimise) == AC_FAIL)
08041 Worked = FALSE;
08042
08043 if (Worked && HaveMadeCurve)
08044 {
08045 Worked = DragFinishedReshapeLine();
08046 }
08047
08048 if (Worked)
08049 {
08050
08051
08052 if (!CopyEditedPathBack())
08053 {
08054
08055 Error::SetError( _R(IDS_OUT_OF_MEMORY) );
08056 Worked = FALSE;
08057 }
08058 }
08059
08060
08061 OriginalPath->InvalidateBoundingRect();
08062
08063
08064
08065 GetApplication()->UpdateSelection();
08066
08067
08068 if (Worked && (RecordBoundsAction::DoRecord(this, &UndoActions, OriginalPath, Optimise) == AC_FAIL))
08069 {
08070 Worked = FALSE;
08071 }
08072 }
08073 }
08074
08075
08076 if (Worked)
08077 {
08078 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,OriginalPath,this);
08079 Worked = UpdateChangedNodes(&ObjChange);
08080 }
08081 }
08082 else
08083 FailAndExecute();
08084
08085 if (!Worked)
08086 {
08087
08088 FailAndExecute();
08089 }
08090 End();
08091 }
08092
08093
08094
08095
08096
08097
08098
08099
08100
08101
08102
08103
08104
08105
08106
08107
08108
08109
08110
08111 BOOL OpReshapeOrAddPoint::DragFinishedAddPoint( )
08112 {
08113
08114 INT32 SplitElement = 0;
08115 PathVerb NewVerbs[6];
08116 DocCoord NewCoords[6];
08117 PathFlags NewFlags[6];
08118 for (INT32 j=0;j<6;j++)
08119 {
08120 NewCoords[j].x = 0;
08121 NewCoords[j].y = 0;
08122 }
08123 UINT32 NumElements = 0;
08124 if (OriginalPath->InkPath.SplitAtPoint(StartMousePos, &SplitElement, &NumElements, NewVerbs, NewCoords))
08125 {
08126
08127 PathVerb* Verbs = NULL;
08128 PathFlags* Flags = NULL;
08129 DocCoord* Coords = NULL;
08130 OriginalPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
08131 ERROR2IF((Verbs == NULL) || (Flags == NULL) || (Coords == NULL), FALSE, "Path array pointer was NULL");
08132
08133
08134
08135
08136
08137
08138
08139
08140 OriginalPath->InkPath.ClearSubSelection();
08141
08142 INT32 NumToChange = 0;
08143
08144 if ((Verbs[SplitElement] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08145 {
08146
08147 NumToChange = 6;
08148
08149 INT32 i;
08150 for (i=0;i<3;i++)
08151 {
08152 NewFlags[i] = Flags[SplitElement+i];
08153 NewFlags[i+3] = Flags[SplitElement+i];
08154 }
08155 for (i = 1; i <=3; i++)
08156 {
08157 NewFlags[i].IsSelected = TRUE;
08158 NewFlags[i].IsSmooth = FALSE;
08159 NewFlags[i].IsRotate = TRUE;
08160 }
08161 NewFlags[0].IsSmooth = Flags[SplitElement].IsSmooth;
08162 NewFlags[0].IsRotate = Flags[SplitElement].IsRotate;
08163 NewFlags[4].IsSmooth = Flags[SplitElement+1].IsSmooth;
08164 NewFlags[4].IsRotate = Flags[SplitElement+1].IsRotate;
08165 NewFlags[5].IsSmooth = Flags[SplitElement+2].IsSmooth;
08166 NewFlags[5].IsRotate = Flags[SplitElement+2].IsRotate;
08167
08168 if (Verbs[SplitElement+2] & PT_CLOSEFIGURE)
08169 NewVerbs[5] |= PT_CLOSEFIGURE;
08170 }
08171 else
08172 {
08173 NumToChange = 2;
08174 NewFlags[0] = NewFlags[1] = Flags[SplitElement];
08175 NewFlags[0].IsSmooth = NewFlags[0].IsRotate = FALSE;
08176 NewFlags[0].IsSelected = TRUE;
08177 if (Verbs[SplitElement] & PT_CLOSEFIGURE)
08178 NewVerbs[1] |= PT_CLOSEFIGURE;
08179 }
08180
08181
08182
08183 Action* UnAction;
08184 ActionCode Act = RemovePathElementAction::Init(this, &UndoActions, NumToChange / 2, SplitElement, (Action**)(&UnAction));
08185 if (Act == AC_FAIL)
08186 {
08187 return FALSE;
08188 }
08189 ((RemovePathElementAction*)UnAction)->RecordPath(OriginalPath);
08190 PathFlags tempflags;
08191 tempflags.IsSmooth = TRUE;
08192 tempflags.IsRotate = TRUE;
08193 tempflags.IsSelected = TRUE;
08194
08195 if (NumToChange == 6)
08196 {
08197 OriginalPath->InkPath.SetPathPosition(SplitElement);
08198 if (!(OriginalPath->InkPath.InsertCurveTo(NewCoords[0], NewCoords[1], NewCoords[2], &tempflags)))
08199 {
08200 return FALSE;
08201 }
08202 }
08203 else
08204 {
08205 if (!(OriginalPath->InkPath.InsertLineTo(NewCoords[0], &tempflags)))
08206 {
08207 return FALSE;
08208 }
08209 }
08210
08211
08212 OriginalPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
08213
08214
08215 ModifyPathAction* ModAction;
08216 Act = ModifyPathAction::Init(this, &UndoActions, NumToChange, (Action**)(&ModAction));
08217 if (Act == AC_FAIL)
08218 {
08219 return FALSE;
08220 }
08221
08222 if ((Act!=AC_NORECORD) && (ModAction!=NULL))
08223 {
08224 PathVerb* ChangedVerbs;
08225 PathFlags* ChangedFlags;
08226 DocCoord* ChangedCoords;
08227 INT32* ChangedIndices;
08228
08229 ALLOC_WITH_FAIL(ChangedVerbs, (PathVerb*) CCMalloc(NumToChange * sizeof(PathVerb)), this);
08230 ALLOC_WITH_FAIL(ChangedFlags, (PathFlags*) CCMalloc(NumToChange* sizeof(PathFlags)), this);
08231 ALLOC_WITH_FAIL(ChangedCoords, (DocCoord*) CCMalloc(NumToChange* sizeof(DocCoord)), this);
08232 ALLOC_WITH_FAIL(ChangedIndices, (INT32*) CCMalloc(NumToChange* sizeof(INT32)), this);
08233
08234 if (!ChangedVerbs || !ChangedFlags || !ChangedCoords || !ChangedIndices)
08235 {
08236 if (ChangedVerbs) CCFree(ChangedVerbs);
08237 if (ChangedFlags) CCFree(ChangedFlags);
08238 if (ChangedCoords) CCFree(ChangedCoords);
08239 if (ChangedIndices) CCFree(ChangedIndices);
08240 return FALSE;
08241 }
08242
08243
08244 for (INT32 i=0; i<NumToChange; i++)
08245 {
08246 ChangedIndices[i] = SplitElement+i;
08247 ChangedVerbs[i] = Verbs[SplitElement+i];
08248 ChangedFlags[i] = Flags[SplitElement+i];
08249 ChangedCoords[i] = Coords[SplitElement+i];
08250 }
08251
08252 ModAction->StoreArrays(ChangedVerbs, ChangedFlags, ChangedCoords, ChangedIndices, OriginalPath);
08253 }
08254
08255
08256 OriginalPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
08257
08258
08259 for (INT32 i=0; i<NumToChange; i++)
08260 {
08261 Verbs[SplitElement+i] = NewVerbs[i];
08262 Flags[SplitElement+i] = NewFlags[i];
08263 Coords[SplitElement+i] = NewCoords[i];
08264 }
08265
08266 GetApplication()->FindSelection()->UpdateBounds();
08267 }
08268 else
08269 {
08270 return FALSE;
08271 }
08272
08273 return TRUE;
08274 }
08275
08276
08277
08278
08279
08280
08281
08282
08283
08284
08285
08286
08287
08288
08289
08290
08291
08292
08293 BOOL OpReshapeOrAddPoint::DragFinishedReshapeLine( )
08294 {
08295 return OpMakeSegmentsCurves::CarryOut(Index, Index-1, OriginalPath, this, &UndoActions);
08296 }
08297
08298
08299
08300
08301
08302
08303
08304
08305
08306
08307
08308
08309
08310
08311
08312
08313
08314 BOOL OpReshapeOrAddPoint::BuildEditPath()
08315 {
08316
08317 UINT32 NumCoords = OriginalPath->InkPath.GetNumCoords();
08318 if (!EditPath.Initialise(NumCoords, 24))
08319 return FALSE;
08320 if (!EditPath.CopyPathDataFrom(&(OriginalPath->InkPath)))
08321 return FALSE;
08322
08323
08324 PathFlags* Flags;
08325 PathVerb* Verbs;
08326 DocCoord* Coords;
08327 EditPath.GetPathArrays(&Verbs, &Coords, &Flags);
08328 if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_LINETO)
08329 {
08330 const DocCoord Start = Coords[Index-1];
08331 const DocCoord End = Coords[Index];
08332 BOOL IsClosed = OriginalPath->InkPath.GetVerbArray()[Index] & PT_CLOSEFIGURE;
08333 BOOL IsSelected = OriginalPath->InkPath.GetFlagArray()[Index].IsSelected;
08334
08335
08336 DocCoord OneThird((Start.x+(End.x-Start.x)/3), (Start.y+(End.y-Start.y)/3) );
08337 DocCoord TwoThird((End.x+(Start.x-End.x)/3), (End.y+(Start.y-End.y)/3) );
08338 EditPath.SetPathPosition(Index);
08339 if (!EditPath.InsertCurveTo(OneThird, TwoThird, End))
08340 return FALSE;
08341
08342
08343 if (!EditPath.DeleteSection(Index+3, 1))
08344 return FALSE;
08345
08346
08347 EditPath.GetPathArrays(&Verbs, &Coords, &Flags);
08348 Flags[Index+2].IsSelected = IsSelected;
08349 if (IsClosed)
08350 Verbs[Index+2] = Verbs[Index+2] | PT_CLOSEFIGURE;
08351
08352
08353 HaveMadeCurve = TRUE;
08354 INT32 tempel;
08355 EditPath.SqrDistanceToPoint(StartMousePos, &tempel, ¶mdist);
08356 }
08357
08358
08359 EditPath.ClearNeedToRender();
08360
08361
08362 EditPath.GetPathArrays(&Verbs, &Coords, &Flags);
08363 if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08364 Flags[Index+2].NeedToRender = TRUE;
08365 else
08366 Flags[Index].NeedToRender = TRUE;
08367
08368
08369 Flags[Index-1].IsSmooth = FALSE;
08370 Flags[Index+2].IsSmooth = FALSE;
08371
08372
08373 if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08374 {
08375 INT32 Opposite = EditPath.FindOppositeControlPoint(Index);
08376 if ( (Opposite>=0) && (Flags[Opposite+1].IsRotate || Flags[Index-1].IsRotate) )
08377 Flags[Opposite+1].NeedToRender = TRUE;
08378
08379 Opposite = EditPath.FindOppositeControlPoint(Index+1);
08380 if ( (Opposite>=0) && (Flags[Opposite-1].IsRotate || Flags[Index+2].IsRotate) )
08381 Flags[Opposite+2].NeedToRender = TRUE;
08382 }
08383
08384
08385 return TRUE;
08386 }
08387
08388
08389
08390
08391
08392
08393
08394
08395
08396
08397
08398
08399
08400
08401
08402
08403
08404
08405
08406
08407
08408
08409
08410
08411
08412
08413
08414
08415
08416
08417
08418
08419
08420
08421
08422 void OpReshapeOrAddPoint::RecalculatePath( DocCoord Offset )
08423 {
08424
08425 const double factor = 0.656875;
08426 PathVerb* Verbs = EditPath.GetVerbArray();
08427 DocCoord* Coords = EditPath.GetCoordArray();
08428 PathFlags* Flags = EditPath.GetFlagArray();
08429 if (Verbs[Index] == PT_BEZIERTO)
08430 {
08431
08432
08433
08434
08435
08436
08437
08438
08439 DocCoord ControlOffset;
08440 INT32 OppositeIndex = EditPath.FindOppositeControlPoint(Index);
08441 ControlOffset.x = (INT32)(OrigControl1.x + (Offset.x) * factor / paramdist);
08442 ControlOffset.y = (INT32)(OrigControl1.y + (Offset.y) * factor / paramdist);
08443
08444 ControlOffset.x -= Coords[Index].x;
08445 ControlOffset.y -= Coords[Index].y;
08446
08447 if (Flags[Index-1].IsRotate && OppositeIndex >= 0)
08448 {
08449 EditPath.CalcRotate(Coords[Index-1], &Coords[Index], &Coords[OppositeIndex], ControlOffset);
08450 }
08451 else
08452 {
08453 Coords[Index].x += ControlOffset.x;
08454 Coords[Index].y += ControlOffset.y;
08455 }
08456
08457
08458
08459 if ((Index > 1) && ((Verbs[Index-1] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) )
08460 Flags[Index-2].IsSmooth = FALSE;
08461 Flags[Index-1].IsSmooth = FALSE;
08462 Flags[Index].IsSmooth = FALSE;
08463 Flags[Index+1].IsSmooth = FALSE;
08464 Flags[Index+2].IsSmooth = FALSE;
08465 if ((Index < EditPath.GetNumCoords()-3) && ((Verbs[Index+3] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) )
08466 Flags[Index+3].IsSmooth = FALSE;
08467
08468
08469
08470 if (Index == 1)
08471
08472 {
08473 Flags[Index].IsRotate = FALSE;
08474 Flags[Index-1].IsRotate = FALSE;
08475 }
08476 if (Index == EditPath.GetNumCoords()-3)
08477 {
08478 Flags[Index+1].IsRotate = FALSE;
08479 Flags[Index+2].IsRotate = FALSE;
08480 }
08481
08482 ControlOffset.x = (INT32)(OrigControl2.x + (Offset.x) * factor / (1.0-paramdist));
08483 ControlOffset.y = (INT32)(OrigControl2.y + (Offset.y) * factor / (1.0-paramdist));
08484
08485 ControlOffset.x -= Coords[Index+1].x;
08486 ControlOffset.y -= Coords[Index+1].y;
08487 OppositeIndex = EditPath.FindOppositeControlPoint(Index+1);
08488
08489 if (Flags[Index+2].IsRotate && OppositeIndex >= 0)
08490 {
08491 EditPath.CalcRotate(Coords[Index+2], &Coords[Index+1], &Coords[OppositeIndex], ControlOffset);
08492 }
08493 else
08494 {
08495 Coords[Index+1].x += ControlOffset.x;
08496 Coords[Index+1].y += ControlOffset.y;
08497 }
08498 }
08499 }
08500
08501
08502
08503
08504
08505
08506
08507
08508
08509
08510
08511
08512
08513 BOOL OpReshapeOrAddPoint::Init()
08514 {
08515 return (RegisterOpDescriptor(
08516 0,
08517 _R(IDS_NODEPATH_EDIT),
08518 CC_RUNTIME_CLASS(OpReshapeOrAddPoint),
08519 OPTOKEN_NODEPATH,
08520 OpReshapeOrAddPoint::GetState,
08521 0,
08522 _R(IDBBL_NODEPATHOP),
08523 0 ) );
08524 }
08525
08526
08527
08528
08529
08530
08531
08532
08533
08534
08535
08536
08537
08538
08539 OpReshapeOrAddPoint::OpReshapeOrAddPoint() : OpNodePathEditBlob()
08540 {
08541 Index = -1;
08542 paramdist = -1;
08543 HaveMadeCurve = FALSE;
08544 };
08545
08546
08547
08548
08549
08550
08551
08552
08553
08554
08555
08556
08557
08558
08559
08560
08561
08562 OpState OpReshapeOrAddPoint::GetState(String_256* Description, OpDescriptor*)
08563 {
08564 OpState Blobby;
08565
08566 return Blobby;
08567 }
08568
08569
08570
08571
08572
08573
08574
08575
08576
08577 void OpReshapeOrAddPoint::SetStatusLineHelp()
08578 {
08579 String_256 HelpString;
08580 if (StartMousePos == FurthestPoint)
08581 HelpString = String_256(_R(IDS_PATHDRAGADDREFORM));
08582 else
08583 HelpString = String_256(_R(IDS_PATHDRAGFINISHREFORM));
08584
08585 GetApplication()->UpdateStatusBarText(&HelpString, FALSE);
08586 }
08587
08588
08589
08590
08591
08593
08595
08596
08597
08598
08599
08600
08601
08602
08603
08604
08605
08606
08607
08608
08609
08610
08611 ModifyPathAction::ModifyPathAction()
08612 {
08613 ChangedVerbs = NULL;
08614 ChangedFlags = NULL;
08615 ChangedCoords = NULL;
08616 ChangedIndices = NULL;
08617 }
08618
08619
08620
08621
08622
08623
08624
08625
08626
08627
08628
08629
08630
08631
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643
08644
08645
08646
08647
08648
08649
08650 ActionCode ModifyPathAction::Init( Operation* pOp,
08651 ActionList* pActionList,
08652 INT32 NumChangedElements,
08653 Action** NewAction)
08654 {
08655 UINT32 ActSize = sizeof(ModifyPathAction) +
08656 NumChangedElements * (sizeof(PathVerb)+sizeof(PathFlags)+sizeof(DocCoord)+sizeof(INT32));
08657
08658 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(ModifyPathAction), NewAction);
08659 if ((Ac==AC_OK) && (*NewAction != NULL))
08660 ((ModifyPathAction*)*NewAction)->NumElements = NumChangedElements;
08661
08662
08663
08664 return Ac;
08665 }
08666
08667
08668
08669
08670
08671
08672
08673
08674
08675
08676
08677
08678
08679
08680
08681
08682
08683
08684
08685
08686
08687 void ModifyPathAction::StoreArrays(PathVerb* Verbs, PathFlags* Flags, DocCoord* Coords,
08688 INT32* Indices, NodePath* WhichPath)
08689 {
08690 ChangedPath = WhichPath;
08691 ChangedVerbs = Verbs;
08692 ChangedFlags = Flags;
08693 ChangedCoords = Coords;
08694 ChangedIndices = Indices;
08695 }
08696
08697
08698
08699
08700
08701
08702
08703
08704
08705
08706
08707
08708
08709
08710
08711
08712
08713
08714
08715
08716
08717 ActionCode ModifyPathAction::Execute()
08718 {
08719
08720
08721
08722
08723
08724
08725
08726 ModifyPathAction* ModAction;
08727
08728 ActionCode Act;
08729 Act = ModifyPathAction::Init(pOperation, pOppositeActLst, NumElements, (Action**)(&ModAction));
08730 if (Act == AC_FAIL)
08731 return AC_FAIL;
08732
08733
08734 Document* pDoc = GetWorkingDoc();
08735 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing modifypath" );
08736 Spread* pSpread = ChangedPath->FindParentSpread();
08737 DocRect Invalid = ChangedPath->GetUnionBlobBoundingRect();
08738 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
08739
08740
08741
08742 PathVerb* Verbs = ChangedPath->InkPath.GetVerbArray();
08743 DocCoord* Coords = ChangedPath->InkPath.GetCoordArray();
08744 PathFlags* Flags = ChangedPath->InkPath.GetFlagArray();
08745
08746
08747
08748 PathVerb TempVerb;
08749 DocCoord TempCoord;
08750 PathFlags TempFlag;
08751
08752 for (INT32 i=0;i<NumElements;i++)
08753 {
08754 TempVerb = Verbs[ChangedIndices[i]];
08755 TempCoord = Coords[ChangedIndices[i]];
08756 TempFlag = Flags[ChangedIndices[i]];
08757 Verbs[ChangedIndices[i]] = ChangedVerbs[i];
08758 Coords[ChangedIndices[i]] = ChangedCoords[i];
08759 Flags[ChangedIndices[i]] = ChangedFlags[i];
08760 ChangedVerbs[i] = TempVerb;
08761 ChangedCoords[i] = TempCoord;
08762 ChangedFlags[i] = TempFlag;
08763
08764 }
08765
08766
08767
08768
08769 if (Act==AC_OK && ModAction!=NULL)
08770 ModAction->StoreArrays(ChangedVerbs, ChangedFlags, ChangedCoords, ChangedIndices, ChangedPath);
08771
08772
08773
08774 ChangedVerbs = NULL;
08775 ChangedCoords = NULL;
08776 ChangedFlags = NULL;
08777 ChangedIndices = NULL;
08778
08779 ChangedPath->InvalidateBoundingRect();
08780
08781
08782 Invalid = ChangedPath->GetUnionBlobBoundingRect();
08783 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
08784
08785 return Act;
08786 }
08787
08788
08789
08790
08791 ModifyPathAction::~ModifyPathAction()
08792 {
08793 if (ChangedVerbs)
08794 CCFree(ChangedVerbs);
08795 if (ChangedCoords)
08796 CCFree(ChangedCoords);
08797 if (ChangedFlags)
08798 CCFree(ChangedFlags);
08799 if (ChangedIndices)
08800 CCFree(ChangedIndices);
08801 }
08802
08804
08806
08807
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821
08822 RemovePathElementAction::RemovePathElementAction()
08823 {
08824 }
08825
08826
08827
08828
08829
08830
08831
08832
08833
08834
08835
08836
08837
08838
08839
08840
08841
08842
08843
08844
08845
08846
08847
08848
08849
08850
08851
08852
08853
08854
08855
08856
08857
08858
08859 ActionCode RemovePathElementAction::Init( Operation* pOp,
08860 ActionList* pActionList,
08861 INT32 NumChangedElements,
08862 INT32 ChangedIndex,
08863 Action** NewAction)
08864 {
08865 UINT32 ActSize = sizeof(RemovePathElementAction) +
08866 NumChangedElements * (sizeof(PathVerb)+sizeof(PathFlags)+sizeof(DocCoord));
08867
08868 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(RemovePathElementAction), NewAction);
08869
08870 if ((Ac == AC_OK) && (*NewAction != NULL))
08871 {
08872 ((RemovePathElementAction*)*NewAction)->NumElements = NumChangedElements;
08873 ((RemovePathElementAction*)*NewAction)->FirstChangedIndex = ChangedIndex;
08874 }
08875
08876 return Ac;
08877 }
08878
08879
08880
08881
08882
08883
08884
08885
08886
08887
08888
08889
08890
08891
08892
08893
08894
08895
08896 void RemovePathElementAction::RecordPath(NodePath* WhichPath)
08897 {
08898 ChangedPath = WhichPath;
08899 }
08900
08901 ActionCode RemovePathElementAction::Execute()
08902 {
08903
08904
08905
08906
08907 InsertPathElementAction* ModAction;
08908
08909 ActionCode Act;
08910 Act = InsertPathElementAction::Init(pOperation, pOppositeActLst, NumElements, FirstChangedIndex,
08911 (Action**)(&ModAction));
08912 if (Act == AC_FAIL)
08913 return AC_FAIL;
08914
08915
08916 Document* pDoc = GetWorkingDoc();
08917 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing modifypath" );
08918 Spread* pSpread = ChangedPath->FindParentSpread();
08919 DocRect Invalid = ChangedPath->GetUnionBlobBoundingRect();
08920 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
08921
08922 if ((Act!=AC_NORECORD) && (ModAction!=NULL))
08923 {
08924
08925
08926 PathVerb* ChangedVerbs;
08927 DocCoord* ChangedCoords;
08928 PathFlags* ChangedFlags;
08929
08930 ALLOC_WITH_FAIL(ChangedVerbs,(PathVerb*) CCMalloc(NumElements * sizeof(PathVerb)),pOperation);
08931 ALLOC_WITH_FAIL(ChangedCoords,(DocCoord*) CCMalloc(NumElements * sizeof(DocCoord)),pOperation);
08932 ALLOC_WITH_FAIL(ChangedFlags,(PathFlags*) CCMalloc(NumElements * sizeof(PathFlags)),pOperation);
08933
08934 if (!ChangedVerbs || !ChangedCoords || !ChangedFlags)
08935 {
08936 if (ChangedVerbs) CCFree(ChangedVerbs);
08937 if (ChangedCoords) CCFree(ChangedCoords);
08938 if (ChangedFlags) CCFree(ChangedFlags);
08939 return AC_FAIL;
08940 }
08941
08942
08943 PathVerb* Verbs = ChangedPath->InkPath.GetVerbArray();
08944 DocCoord* Coords = ChangedPath->InkPath.GetCoordArray();
08945 PathFlags* Flags = ChangedPath->InkPath.GetFlagArray();
08946
08947
08948 for (INT32 i=0;i<NumElements;i++)
08949 {
08950 ChangedVerbs[i] = Verbs[FirstChangedIndex+i];
08951 ChangedCoords[i] = Coords[FirstChangedIndex+i];
08952 ChangedFlags[i] = Flags[FirstChangedIndex+i];
08953 }
08954
08955
08956 ModAction->RecordPath(ChangedVerbs, ChangedFlags,ChangedCoords, ChangedPath);
08957 }
08958
08959
08960 ChangedPath->InkPath.DeleteSection(FirstChangedIndex, NumElements);
08961
08962 ChangedPath->InvalidateBoundingRect();
08963
08964
08965 Invalid = ChangedPath->GetUnionBlobBoundingRect();
08966 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
08967
08968 return Act;
08969 }
08970
08971
08972
08973 RemovePathElementAction::~RemovePathElementAction()
08974 {
08975
08976
08977
08978
08979
08980
08981
08982
08983 }
08984
08986
08988
08989
08990
08991
08992
08993
08994
08995
08996
08997
08998
08999
09000
09001
09002
09003
09004 InsertPathElementAction::InsertPathElementAction()
09005 {
09006 ChangedVerbs = NULL;
09007 ChangedFlags = NULL;
09008 ChangedCoords = NULL;
09009 }
09010
09011
09012
09013
09014
09015
09016
09017
09018
09019
09020
09021
09022
09023
09024
09025
09026
09027
09028
09029
09030
09031
09032
09033
09034
09035
09036
09037
09038
09039
09040
09041
09042
09043 ActionCode InsertPathElementAction::Init( Operation* pOp,
09044 ActionList* pActionList,
09045 INT32 NumChangedElements,
09046 INT32 ChangedIndex,
09047 Action** NewAction)
09048 {
09049 UINT32 ActSize = sizeof(InsertPathElementAction) +
09050 NumChangedElements * (sizeof(PathVerb)+sizeof(PathFlags)+sizeof(DocCoord));
09051
09052 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(InsertPathElementAction), NewAction);
09053 if ((Ac == AC_OK) && (*NewAction != NULL))
09054 {
09055 ((InsertPathElementAction*)*NewAction)->NumElements = NumChangedElements;
09056 ((InsertPathElementAction*)*NewAction)->InsertionPoint = ChangedIndex;
09057 }
09058
09059 return Ac;
09060 }
09061
09062
09063
09064
09065
09066
09067
09068
09069
09070
09071
09072
09073
09074
09075
09076
09077
09078
09079
09080
09081
09082
09083
09084 void InsertPathElementAction::RecordPath(PathVerb* Verbs, PathFlags* Flags, DocCoord* Coords,
09085 NodePath* WhichPath)
09086 {
09087 ChangedPath = WhichPath;
09088 ChangedVerbs = Verbs;
09089 ChangedFlags = Flags;
09090 ChangedCoords = Coords;
09091 }
09092
09093 ActionCode InsertPathElementAction::Execute()
09094 {
09095
09096
09097
09098
09099
09100
09101
09102 RemovePathElementAction* ModAction;
09103
09104 ActionCode Act;
09105 Act = RemovePathElementAction::Init(pOperation, pOppositeActLst, NumElements, InsertionPoint, (Action**)(&ModAction));
09106 if (Act == AC_FAIL)
09107 return AC_FAIL;
09108
09109
09110 if (ModAction!=NULL)
09111 ModAction->RecordPath(ChangedPath);
09112
09113
09114 Document* pDoc = GetWorkingDoc();
09115 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing modifypath" );
09116 Spread* pSpread = ChangedPath->FindParentSpread();
09117 DocRect Invalid = ChangedPath->GetUnionBlobBoundingRect();
09118 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09119
09120
09121 if (!ChangedPath->InkPath.InsertSection(InsertionPoint,
09122 NumElements))
09123 return AC_FAIL;
09124
09125
09126
09127
09128 PathVerb* Verbs = ChangedPath->InkPath.GetVerbArray();
09129 DocCoord* Coords = ChangedPath->InkPath.GetCoordArray();
09130 PathFlags* Flags = ChangedPath->InkPath.GetFlagArray();
09131
09132
09133
09134 for (INT32 i=0;i<NumElements;i++)
09135 {
09136 Verbs[i+InsertionPoint] = ChangedVerbs[i];
09137 Coords[i+InsertionPoint] = ChangedCoords[i];
09138 Flags[i+InsertionPoint] = ChangedFlags[i];
09139 }
09140
09141 ChangedPath->InvalidateBoundingRect();
09142
09143 Invalid = ChangedPath->GetUnionBlobBoundingRect();
09144 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09145
09146 return Act;
09147 }
09148
09149 InsertPathElementAction::~InsertPathElementAction()
09150 {
09151 if (ChangedVerbs)
09152 CCFree(ChangedVerbs);
09153 if (ChangedCoords)
09154 CCFree(ChangedCoords);
09155 if (ChangedFlags)
09156 CCFree(ChangedFlags);
09157 }
09158
09160
09162
09163
09164
09165
09166
09167
09168
09169
09170
09171
09172
09173
09174
09175
09176
09177
09178 ModifyElementAction::ModifyElementAction()
09179 {
09180 ChangedPath = NULL;
09181 }
09182
09183
09184
09185
09186
09187
09188
09189
09190
09191
09192
09193
09194
09195
09196
09197
09198
09199
09200
09201
09202
09203
09204
09205
09206
09207
09208
09209
09210
09211
09212
09213
09214
09215
09216
09217
09218
09219
09220 ActionCode ModifyElementAction::Init( Operation* pOp,
09221 ActionList* pActionList,
09222 PathVerb Verb,
09223 PathFlags Flags,
09224 DocCoord Coord,
09225 INT32 Index,
09226 NodePath* WhichPath,
09227 Action** NewAction)
09228 {
09229 UINT32 ActSize = sizeof(ModifyElementAction);
09230
09231 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(ModifyElementAction), NewAction);
09232
09233 if ((Ac == AC_OK) && (*NewAction != NULL))
09234 {
09235 ((ModifyElementAction*)*NewAction)->ChangedVerb = Verb;
09236 ((ModifyElementAction*)*NewAction)->ChangedFlags = Flags;
09237 ((ModifyElementAction*)*NewAction)->ChangedCoord = Coord;
09238 ((ModifyElementAction*)*NewAction)->ChangedIndex = Index;
09239 ((ModifyElementAction*)*NewAction)->ChangedPath = WhichPath;
09240 }
09241
09242 return Ac;
09243 }
09244
09245 ActionCode ModifyElementAction::Execute()
09246 {
09247
09248
09249
09250 ModifyElementAction* ModAction;
09251
09252
09253
09254 PathVerb* Verbs = ChangedPath->InkPath.GetVerbArray();
09255 DocCoord* Coords = ChangedPath->InkPath.GetCoordArray();
09256 PathFlags* Flags = ChangedPath->InkPath.GetFlagArray();
09257
09258
09259
09260 ActionCode Act;
09261 Act = ModifyElementAction::Init(pOperation,
09262 pOppositeActLst,
09263 Verbs[ChangedIndex],
09264 Flags[ChangedIndex],
09265 Coords[ChangedIndex],
09266 ChangedIndex,
09267 ChangedPath,
09268 (Action**)(&ModAction));
09269 if (Act == AC_FAIL)
09270 return AC_FAIL;
09271
09272
09273 Document* pDoc = GetWorkingDoc();
09274 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing modifypath" );
09275 Spread* pSpread = ChangedPath->FindParentSpread();
09276 DocRect Invalid = ChangedPath->GetUnionBlobBoundingRect();
09277 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09278
09279 Verbs[ChangedIndex] = ChangedVerb;
09280 Flags[ChangedIndex] = ChangedFlags;
09281 Coords[ChangedIndex] = ChangedCoord;
09282
09283 ChangedPath->InvalidateBoundingRect();
09284 Invalid = ChangedPath->GetUnionBlobBoundingRect();
09285 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09286
09287 return Act;
09288 }
09289
09290 ModifyElementAction::~ModifyElementAction()
09291 {
09292 }
09293
09295
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313 ModifyFlagsAction::ModifyFlagsAction()
09314 {
09315 ChangedPath = NULL;
09316 }
09317
09318
09319
09320
09321
09322
09323
09324
09325
09326
09327
09328
09329
09330
09331
09332
09333
09334
09335
09336
09337
09338
09339
09340
09341
09342
09343
09344
09345
09346
09347
09348
09349
09350
09351 ActionCode ModifyFlagsAction::Init( Operation* pOp,
09352 ActionList* pActionList,
09353 PathFlags Flags,
09354 INT32 Index,
09355 NodePath* WhichPath,
09356 Action** NewAction)
09357 {
09358 UINT32 ActSize = sizeof(ModifyFlagsAction);
09359
09360 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(ModifyFlagsAction), NewAction);
09361 if ((Ac==AC_OK) && (*NewAction != NULL))
09362 {
09363 ((ModifyFlagsAction*)*NewAction)->ChangedFlags = Flags;
09364 ((ModifyFlagsAction*)*NewAction)->ChangedIndex = Index;
09365 ((ModifyFlagsAction*)*NewAction)->ChangedPath = WhichPath;
09366 }
09367
09368
09369 return Ac;
09370 }
09371
09372 ActionCode ModifyFlagsAction::Execute()
09373 {
09374
09375
09376
09377 ModifyFlagsAction* ModAction;
09378
09379
09380
09381 PathFlags* Flags = ChangedPath->InkPath.GetFlagArray();
09382
09383
09384
09385 ActionCode Act;
09386 Act = ModifyFlagsAction::Init(pOperation,
09387 pOppositeActLst,
09388 Flags[ChangedIndex],
09389 ChangedIndex,
09390 ChangedPath,
09391 (Action**)(&ModAction));
09392 if (Act == AC_FAIL)
09393 return AC_FAIL;
09394
09395
09396 Document* pDoc = GetWorkingDoc();
09397 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing modifypath" );
09398 Spread* pSpread = ChangedPath->FindParentSpread();
09399 DocRect Invalid = ChangedPath->GetUnionBlobBoundingRect();
09400 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09401
09402 Flags[ChangedIndex] = ChangedFlags;
09403
09404 Invalid = ChangedPath->GetUnionBlobBoundingRect();
09405 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09406
09407 return Act;
09408 }
09409
09410 ModifyFlagsAction::~ModifyFlagsAction()
09411 {
09412 }
09413
09415
09417
09418
09419
09420
09421
09422
09423
09424
09425
09426
09427
09428
09429
09430
09431
09432
09433 ModifyFilledAction::ModifyFilledAction()
09434 {
09435 UndoFilled = TRUE;
09436 OldFilledState = FALSE;
09437 }
09438
09439
09440
09441
09442
09443
09444
09445
09446
09447
09448
09449
09450
09451
09452
09453
09454
09455
09456
09457
09458
09459
09460
09461
09462
09463
09464
09465
09466
09467
09468
09469
09470
09471
09472
09473 ActionCode ModifyFilledAction::Init(Operation* pOp,
09474 ActionList* pActionList,
09475 BOOL UndoFillOrStroke,
09476 BOOL FilledFlag,
09477 NodePath* WhichPath,
09478 Action** NewAction)
09479 {
09480 UINT32 ActSize = sizeof(ModifyFilledAction);
09481
09482 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(ModifyFilledAction), NewAction);
09483 if ((Ac==AC_OK) && (*NewAction != NULL))
09484 {
09485 ((ModifyFilledAction*)*NewAction)->UndoFilled = UndoFillOrStroke;
09486 ((ModifyFilledAction*)*NewAction)->OldFilledState = FilledFlag;
09487 ((ModifyFilledAction*)*NewAction)->ChangedPath = WhichPath;
09488 }
09489
09490
09491 return Ac;
09492 }
09493
09494 ActionCode ModifyFilledAction::Execute()
09495 {
09496
09497
09498
09499 ModifyFilledAction* ModAction;
09500
09501
09502
09503 BOOL CurState;
09504 if (UndoFilled)
09505 CurState = ChangedPath->InkPath.IsFilled;
09506 else
09507 CurState = ChangedPath->InkPath.IsStroked;
09508
09509 ActionCode Act;
09510 Act = ModifyFilledAction::Init(pOperation,
09511 pOppositeActLst,
09512 UndoFilled,
09513 CurState,
09514 ChangedPath,
09515 (Action**)(&ModAction));
09516 if (Act == AC_FAIL)
09517 return AC_FAIL;
09518
09519
09520 Document* pDoc = GetWorkingDoc();
09521 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing modifypath" );
09522 Spread* pSpread = ChangedPath->FindParentSpread();
09523 DocRect Invalid = ChangedPath->GetUnionBlobBoundingRect();
09524 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09525
09526 if (UndoFilled)
09527 ChangedPath->InkPath.IsFilled = OldFilledState;
09528 else
09529 ChangedPath->InkPath.IsStroked = OldFilledState;
09530
09531 Invalid = ChangedPath->GetUnionBlobBoundingRect();
09532 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedPath );
09533
09534 return Act;
09535 }
09536
09537 ModifyFilledAction::~ModifyFilledAction()
09538 {
09539 }
09540
09542
09544
09545
09546
09547
09548
09549
09550
09551
09552
09553
09554
09555
09556
09557
09558
09559 RecalcBoundsAction::RecalcBoundsAction()
09560 {
09561 }
09562
09563
09564
09565
09566
09567
09568
09569
09570
09571
09572
09573
09574
09575
09576
09577
09578
09579
09580
09581
09582
09583
09584
09585
09586
09587
09588
09589
09590
09591 ActionCode RecalcBoundsAction::Init( Operation* pOp,
09592 ActionList* pActionList,
09593 NodeRenderableBounded* WhichNode,
09594 Action** NewAction)
09595 {
09596 UINT32 ActSize = sizeof(RecalcBoundsAction);
09597
09598 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(RecalcBoundsAction), NewAction);
09599 if ((Ac == AC_OK) && (*NewAction != NULL))
09600 {
09601 ((RecalcBoundsAction*)*NewAction)->ChangedNode = WhichNode;
09602 ((RecalcBoundsAction*)*NewAction)->OldBounds = WhichNode->GetBoundingRect();
09603 }
09604
09605 return Ac;
09606 }
09607
09608
09609
09610
09611
09612
09613
09614
09615
09616
09617
09618
09619
09620
09621
09622
09623
09624
09625
09626
09627
09628
09629
09630
09631
09632
09633
09634
09635
09636
09637
09638
09639 ActionCode RecalcBoundsAction::DoRecalc(Operation* pOp,
09640 ActionList* pActionList,
09641 NodeRenderableBounded* WhichNode,
09642 BOOL OptimiseRedraw)
09643 {
09644 ERROR3IF(OptimiseRedraw && !WhichNode->IsNodePath(),"Can't optimise redraw for a non-path object");
09645
09646 RecalcBoundsAction* RecAction;
09647 ActionCode Act = RecalcBoundsAction::Init(pOp, pActionList, WhichNode, (Action**)&RecAction);
09648 if (Act != AC_FAIL)
09649 {
09650
09651 Document* pDoc = pOp->GetWorkingDoc();
09652 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document in RecordBoundsAction::DoRecord" );
09653 Spread* pSpread = WhichNode->FindParentSpread();
09654 DocRect Invalid;
09655
09656 ((NodePath*)WhichNode)->ReleaseCached();
09657
09658
09659 if (WhichNode->IsNodePath() && OptimiseRedraw)
09660 OptimiseRedraw = CauseOptimisedRedraw((NodePath*)WhichNode, pDoc, pSpread);
09661 else
09662 OptimiseRedraw = FALSE;
09663
09664 if (!OptimiseRedraw)
09665 pDoc->ForceRedraw( pSpread, WhichNode->GetUnionBlobBoundingRect());
09666 }
09667 return Act;
09668 }
09669
09670
09671
09672
09673
09674
09675
09676
09677
09678
09679
09680
09681
09682
09683
09684
09685
09686 ActionCode RecalcBoundsAction::Execute()
09687 {
09688
09689
09690 RecordBoundsAction* ReAction;
09691
09692
09693
09694 ActionCode Act;
09695 Act = RecordBoundsAction::Init(pOperation,
09696 pOppositeActLst,
09697 ChangedNode,
09698 (Action**)(&ReAction));
09699 if (Act == AC_FAIL)
09700 return AC_FAIL;
09701
09702
09703 Document* pDoc = GetWorkingDoc();
09704 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing RecalcBounds" );
09705 Spread* pSpread = ChangedNode->FindParentSpread();
09706
09707 if (pSpread != NULL)
09708 {
09709 DocRect Invalid = ChangedNode->GetUnionBlobBoundingRect();
09710 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedNode );
09711
09712
09713 ChangedNode->InvalidateBoundingRect();
09714 }
09715
09716 return Act;
09717 }
09718
09719 RecalcBoundsAction::~RecalcBoundsAction()
09720 {
09721 }
09722
09723
09724
09725
09726
09727
09728
09729
09730
09731
09732
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744 BOOL RecalcBoundsAction::CauseOptimisedRedraw(NodePath* pChangedPath, Document* pDoc, Spread* pSpread)
09745 {
09746
09747 if (pChangedPath->InkPath.IsFilled)
09748 return FALSE;
09749
09750
09751 CCAttrMap AttribMap(30);
09752 if (!pChangedPath->FindAppliedAttributes(&AttribMap))
09753 return FALSE;
09754
09755
09756 MILLIPOINT LineWidth = 0;
09757 void* pLineWidth = NULL;
09758 AttribMap.Lookup( CC_RUNTIME_CLASS(AttrLineWidth), pLineWidth );
09759 ERROR3IF(pLineWidth == NULL, "Did not find line width attribute");
09760 if (pLineWidth != NULL)
09761 LineWidth = ((AttrLineWidth*)pLineWidth)->Value.LineWidth;
09762 else
09763 return FALSE;
09764
09765
09766
09767 void* pDashPat = NULL;
09768 AttribMap.Lookup( CC_RUNTIME_CLASS(AttrDashPattern), pDashPat );
09769 ERROR3IF(pDashPat == NULL, "Did not find dash pattern attribute");
09770 if ((pDashPat == NULL) || (((AttrDashPattern*)pDashPat)->Value.DashPattern.Elements != 0) )
09771 return FALSE;
09772
09773
09774 MILLIPOINT MitreLimit = 0;
09775 void* pMitreAttr = NULL;
09776 AttribMap.Lookup( CC_RUNTIME_CLASS(AttrMitreLimit),pMitreAttr);
09777 ERROR3IF(pMitreAttr == NULL, "Did not find mitre attribute");
09778 if (pMitreAttr != NULL)
09779 MitreLimit = ((AttrMitreLimit*)pLineWidth)->Value.MitreLimit;
09780 else
09781 return FALSE;
09782
09783
09784
09785 AttrBrushType* pAttrBrush = (AttrBrushType*) pChangedPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType));
09786 if (pAttrBrush != NULL && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush)
09787 {
09788 pAttrBrush->FlushCache();
09789 DocRect Redraw = pAttrBrush->GetAttrBoundingRect(pChangedPath);
09790 pDoc->ForceRedraw(pSpread, Redraw, FALSE, pChangedPath);
09791 }
09792
09793
09794 AttrEndArrow* pEndArrow = (AttrEndArrow*) pChangedPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrEndArrow));
09795 AttrStartArrow* pStartArrow = (AttrStartArrow*) pChangedPath->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartArrow));
09796
09797
09798
09799 if (pEndArrow != NULL)
09800 {
09801 DocRect Redraw = pEndArrow->GetAttrBoundingRect(pChangedPath, &AttribMap);
09802 pDoc->ForceRedraw( pSpread, Redraw, FALSE, pChangedPath );
09803 }
09804 if (pStartArrow != NULL)
09805 {
09806 DocRect Redraw = pStartArrow->GetAttrBoundingRect(pChangedPath, &AttribMap);
09807 pDoc->ForceRedraw( pSpread, Redraw, FALSE, pChangedPath );
09808 }
09809
09810
09811 MILLIPOINT InflationSize = LineWidth + MitreLimit*4;
09812 const INT32 NumPoints = pChangedPath->InkPath.GetNumCoords();
09813 INT32 loop = 0;
09814 INT32 Previous = 0;
09815 PathVerb* Verbs = NULL;
09816 DocCoord* Coords = NULL;
09817 PathFlags* Flags = NULL;
09818 pChangedPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
09819
09820 if (pChangedPath->InkPath.FindNextEndPoint(&loop))
09821 {
09822 while (loop < NumPoints)
09823 {
09824
09825 if (Flags[loop].NeedToRender)
09826 {
09827
09828 DocRect Invalid(Coords[Previous], Coords[Previous]);
09829 while (Previous < loop)
09830 {
09831 Previous++;
09832 Invalid.IncludePoint(Coords[Previous]);
09833 }
09834
09835
09836 Invalid.Inflate(InflationSize);
09837 pDoc->ForceRedraw( pSpread, Invalid, FALSE, pChangedPath );
09838 }
09839
09840
09841 Previous = loop;
09842 if (!pChangedPath->InkPath.FindNextEndPoint(&loop))
09843 break;
09844 }
09845 }
09846 else
09847 return FALSE;
09848
09849 return TRUE;
09850 }
09851
09852
09853
09855
09857
09858
09859
09860
09861
09862
09863
09864
09865
09866
09867
09868
09869
09870
09871
09872 RecordBoundsAction::RecordBoundsAction()
09873 {
09874 }
09875
09876
09877
09878
09879
09880
09881
09882
09883
09884
09885
09886
09887
09888
09889
09890
09891
09892
09893
09894
09895
09896
09897
09898
09899
09900
09901
09902
09903
09904 ActionCode RecordBoundsAction::Init( Operation* pOp,
09905 ActionList* pActionList,
09906 NodeRenderableBounded* WhichNode,
09907 Action** NewAction)
09908 {
09909 UINT32 ActSize = sizeof(RecordBoundsAction);
09910
09911 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(RecordBoundsAction), NewAction);
09912 if ((Ac == AC_OK) && (*NewAction != NULL))
09913 ((RecordBoundsAction*)*NewAction)->ChangedNode = WhichNode;
09914
09915 return Ac;
09916 }
09917
09918
09919
09920
09921
09922
09923
09924
09925
09926
09927
09928
09929
09930
09931
09932
09933
09934
09935
09936
09937
09938
09939
09940
09941
09942
09943
09944 ActionCode RecordBoundsAction::DoRecord(Operation* pOp,
09945 ActionList* pActionList,
09946 NodeRenderableBounded* WhichNode,
09947 BOOL OptimiseRedraw)
09948 {
09949 ERROR3IF(OptimiseRedraw && !WhichNode->IsNodePath(),"Can't optimise redraw for a non-path object");
09950
09951 RecordBoundsAction* RecAction;
09952 ActionCode Act = RecordBoundsAction::Init(pOp, pActionList, WhichNode, (Action**)&RecAction);
09953 if (Act != AC_FAIL)
09954 {
09955
09956 Document* pDoc = pOp->GetWorkingDoc();
09957 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document in RecordBoundsAction::DoRecord" );
09958
09959 Spread* pSpread = WhichNode->FindParentSpread();
09960
09961
09962 if (WhichNode->IsNodePath() && OptimiseRedraw)
09963 OptimiseRedraw = RecalcBoundsAction::CauseOptimisedRedraw((NodePath*)WhichNode, pDoc, pSpread);
09964 else
09965 OptimiseRedraw = FALSE;
09966
09967 if (!OptimiseRedraw)
09968 pDoc->ForceRedraw( pSpread, WhichNode->GetUnionBlobBoundingRect(), FALSE, WhichNode);
09969 }
09970 return Act;
09971 }
09972
09973
09974
09975
09976
09977
09978
09979
09980
09981
09982
09983
09984
09985
09986
09987
09988
09989 ActionCode RecordBoundsAction::Execute()
09990 {
09991
09992
09993 RecalcBoundsAction* ReAction;
09994
09995
09996
09997 ActionCode Act;
09998 Act = RecalcBoundsAction::Init(pOperation,
09999 pOppositeActLst,
10000 ChangedNode,
10001 (Action**)(&ReAction));
10002 if (Act == AC_FAIL)
10003 return AC_FAIL;
10004
10005
10006 Document* pDoc = GetWorkingDoc();
10007 ERROR2IF( pDoc == NULL, AC_FAIL, "There was no current document when undoing RecalcBounds" );
10008 Spread* pSpread = ChangedNode->FindParentSpread();
10009
10010 if (pSpread != NULL)
10011 {
10012 DocRect Invalid = ChangedNode->GetUnionBlobBoundingRect();
10013 pDoc->ForceRedraw( pSpread, Invalid, FALSE, ChangedNode );
10014 }
10015
10016 return Act;
10017 }
10018
10019
10020
10021 RecordBoundsAction::~RecordBoundsAction()
10022 {
10023 }
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039 SavePathArraysAction::SavePathArraysAction()
10040 {
10041 ChangedPath = NULL;
10042 ChangedVerbs = NULL;
10043 ChangedFlags = NULL;
10044 ChangedCoords = NULL;
10045 }
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058 SavePathArraysAction::~SavePathArraysAction()
10059 {
10060 if (ChangedVerbs)
10061 CCFree(ChangedVerbs);
10062 if (ChangedCoords)
10063 CCFree(ChangedCoords);
10064 if (ChangedFlags)
10065 CCFree(ChangedFlags);
10066 }
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090 ActionCode SavePathArraysAction::DoRecord(Operation* pOp, ActionList* pActionList, Path* pPath)
10091 {
10092 SavePathArraysAction* SaveAction;
10093 ActionCode Act = SavePathArraysAction::Init(pOp, pActionList, pPath, (Action**)&SaveAction, TRUE);
10094 return Act;
10095 }
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136 ActionCode SavePathArraysAction::Init(Operation* pOp,
10137 ActionList* pActionList,
10138 Path* pPath,
10139 Action** NewAction,
10140 BOOL CreateArrays)
10141 {
10142 ERROR1IF(pPath==NULL,AC_FAIL,"SavePathArraysAction::Init() passed a NULL path pointer");
10143
10144 UINT32 NumElements = pPath->GetNumCoords();
10145 UINT32 ActSize = sizeof(SavePathArraysAction) + NumElements*(sizeof(PathVerb) +
10146 sizeof(PathFlags) +
10147 sizeof(DocCoord) );
10148
10149 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(SavePathArraysAction), NewAction);
10150
10151 SavePathArraysAction* CreatedAction = (SavePathArraysAction*)(*NewAction);
10152 if (CreatedAction!=NULL)
10153 {
10154 CreatedAction->ChangedPath = pPath;
10155 if (CreateArrays)
10156 CreatedAction->SetUpArrays(pPath,pOp);
10157 }
10158 return Ac;
10159 }
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176 ActionCode SavePathArraysAction::SetUpArrays(Path* pPath, Operation* pOp)
10177 {
10178 if (ChangedFlags!=NULL || ChangedVerbs!=NULL || ChangedCoords!=NULL)
10179 {
10180 ENSURE(TRUE,"SavePathArraysAction::SetUpArrays() failed");
10181 return AC_FAIL;
10182 }
10183
10184 if (!SavePathArrays(pPath, pOp, &ChangedFlags, &ChangedVerbs, &ChangedCoords))
10185 return AC_FAIL;
10186
10187 return AC_OK;
10188 }
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207 ActionCode SavePathArraysAction::Execute()
10208 {
10209
10210 SavePathArraysAction* SaveAction;
10211
10212 ActionCode Act;
10213 Act = SavePathArraysAction::Init(pOperation, pOppositeActLst, ChangedPath, (Action**)(&SaveAction), FALSE);
10214 if (Act == AC_FAIL)
10215 return AC_FAIL;
10216
10217
10218 SwapPathArrays();
10219
10220
10221 if (SaveAction!=NULL)
10222 {
10223 SaveAction->ChangedFlags = ChangedFlags;
10224 SaveAction->ChangedVerbs = ChangedVerbs;
10225 SaveAction->ChangedCoords = ChangedCoords;
10226
10227
10228
10229 ChangedVerbs = NULL;
10230 ChangedCoords = NULL;
10231 ChangedFlags = NULL;
10232 }
10233
10234 return Act;
10235 }
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
10258
10259
10260
10261 BOOL SavePathArraysAction::SavePathArrays( Path* pPath,
10262 Operation* pOp,
10263 PathFlags** pFlags,
10264 PathVerb** pVerbs,
10265 DocCoord** pCoords)
10266 {
10267 UINT32 NumElements = pPath->GetNumCoords();
10268 PathFlags* DFlags;
10269 PathVerb* DVerbs;
10270 DocCoord* DCoords;
10271
10272 ALLOC_WITH_FAIL(DVerbs,(PathVerb*) CCMalloc(NumElements * sizeof(PathVerb)),pOp);
10273 ALLOC_WITH_FAIL(DCoords,(DocCoord*) CCMalloc(NumElements * sizeof(DocCoord)),pOp);
10274 ALLOC_WITH_FAIL(DFlags,(PathFlags*) CCMalloc(NumElements * sizeof(PathFlags)),pOp);
10275
10276 if (!DVerbs || !DCoords || !DFlags)
10277 {
10278 if (DVerbs) CCFree(DVerbs);
10279 if (DCoords) CCFree(DCoords);
10280 if (DFlags) CCFree(DFlags);
10281
10282 *pFlags=NULL;
10283 *pVerbs=NULL;
10284 *pCoords=NULL;
10285
10286 return FALSE;
10287 }
10288
10289
10290 DocCoord* SCoords = pPath->GetCoordArray();
10291 PathFlags* SFlags = pPath->GetFlagArray();
10292 PathVerb* SVerbs = pPath->GetVerbArray();
10293
10294
10295 memmove((void*)(DCoords), (void*)(SCoords), NumElements*sizeof(DocCoord));
10296 memmove((void*)(DVerbs), (void*)(SVerbs), NumElements*sizeof(PathVerb));
10297 memmove((void*)(DFlags), (void*)(SFlags), NumElements*sizeof(PathFlags));
10298
10299 *pFlags = DFlags;
10300 *pVerbs = DVerbs;
10301 *pCoords = DCoords;
10302
10303 return TRUE;
10304 }
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319 void SavePathArraysAction::SwapPathArrays()
10320 {
10321 INT32 NumElements = ChangedPath->GetNumCoords();
10322 PathVerb* Verbs = ChangedPath->GetVerbArray();
10323 DocCoord* Coords = ChangedPath->GetCoordArray();
10324 PathFlags* Flags = ChangedPath->GetFlagArray();
10325
10326 PathVerb TempVerb;
10327 DocCoord TempCoord;
10328 PathFlags TempFlag;
10329
10330 for (INT32 i=0; i<NumElements; i++)
10331 {
10332 TempVerb=Verbs[i]; Verbs[i]=ChangedVerbs[i]; ChangedVerbs[i]=TempVerb;
10333 TempCoord=Coords[i]; Coords[i]=ChangedCoords[i]; ChangedCoords[i]=TempCoord;
10334 TempFlag=Flags[i]; Flags[i]=ChangedFlags[i]; ChangedFlags[i]=TempFlag;
10335 }
10336 }
10337
10338
10339
10340
10341
10342
10343
10345
10346
10347
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10362
10363
10364
10365
10366
10367
10368
10369
10370
10371
10372
10373
10374
10375
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10481
10482
10483
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497
10498
10499
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
10536
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549 BOOL OpCloseNodePaths::Init()
10550 {
10551 const INT32 HID_AUTOCLOSEPATHS = 0;
10552 BTNOP( AUTOCLOSEPATHS, OpCloseNodePaths, ARRANGE)
10553 return TRUE;
10554 }
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569 OpState OpCloseNodePaths::GetState(String_256* Description, OpDescriptor*)
10570 {
10571 OpState Blobby(FALSE, TRUE);
10572
10573
10574 SelRange* pSelection = GetApplication()->FindSelection();
10575 ERROR2IF(pSelection == NULL, Blobby, "No SelRange!");
10576 Node* pSelNode = pSelection->FindFirst();
10577
10578
10579 while (pSelNode != NULL)
10580 {
10581 if (pSelNode->IsNodePath())
10582 {
10583 if (IsThisPathCloseable((NodePath*)pSelNode))
10584 {
10585 Blobby.Greyed = FALSE;
10586 break;
10587 }
10588 }
10589
10590 pSelNode = pSelection->FindNext(pSelNode);
10591 }
10592
10593 return Blobby;
10594 }
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606
10607
10608
10609 void OpCloseNodePaths::DoWithParam(OpDescriptor* pOpDesc, OpParam* pOpParam)
10610 {
10611 BeginSlowJob();
10612
10613 BOOL ok = TRUE;
10614 AddCurveFlag = pOpParam->Param1;
10615 AddSmoothFlag = pOpParam->Param2;
10616 IsPathClosing = TRUE;
10617
10618
10619 if (ok)
10620 ok = DoStartSelOp(TRUE, TRUE);
10621
10622
10623 SelRange* pSelection = GetApplication()->FindSelection();
10624 Node* pSelNode = pSelection->FindFirst();
10625
10626
10627 while (ok && (pSelNode != NULL))
10628 {
10629 if (pSelNode->IsNodePath())
10630 {
10631 if (IsThisPathCloseable((NodePath*)pSelNode))
10632 {
10633 NodePath *pPath = (NodePath*)pSelNode;
10634
10635
10636
10637 ObjChangeParam ObjChange(OBJCHANGE_STARTING,ObjChangeFlags(), pPath, this);
10638 if (pPath->AllowOp(&ObjChange))
10639 ok = CloseThisPath(pPath);
10640 }
10641 }
10642
10643 pSelNode = pSelection->FindNext(pSelNode);
10644 }
10645
10646
10647 if (ok)
10648 {
10649 ObjChangeParam ObjFinished(OBJCHANGE_FINISHED, ObjChangeFlags(), NULL, this);
10650 ok = UpdateChangedNodes(&ObjFinished);
10651 }
10652
10653 if (!ok)
10654 {
10655 FailAndExecute();
10656 InformError();
10657 }
10658
10659 End();
10660 }
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675 BOOL OpCloseNodePaths::CloseThisPath(NodePath* pPath)
10676 {
10677 PathFlags* Flags = NULL;
10678 PathVerb* Verbs = NULL;
10679 DocCoord* Coords = NULL;
10680 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
10681 ERROR2IF( (Flags==NULL) || (Verbs==NULL) || (Coords==NULL), FALSE, "Path array pointer was NULL");
10682 INT32 NumCoords = pPath->InkPath.GetNumCoords();
10683
10684
10685 InsertPosition = NumCoords-1;
10686 OriginalPath = pPath;
10687 StartMousePos = Coords[NumCoords-1];
10688 LastMousePos = Coords[NumCoords-1];
10689 StartSpread = pPath->FindParentSpread();
10690 UpdatePoint = -1;
10691 ERROR2IF( StartSpread==NULL, FALSE, "Path was not on a spread");
10692
10693
10694 BOOL ok = BuildEditPath(LastMousePos);
10695
10696 if (ok)
10697 ok = CompleteThisPath(StartMousePos);
10698
10699 EditPath.ClearPath();
10700
10701 return ok;
10702 }
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717 BOOL OpCloseNodePaths::IsThisPathCloseable(NodePath* pPath)
10718 {
10719 BOOL Closeable = FALSE;
10720 PathFlags* Flags = NULL;
10721 PathVerb* Verbs = NULL;
10722 pPath->InkPath.GetPathArrays(&Verbs, NULL, &Flags);
10723 if ((Flags==NULL) || (Verbs==NULL))
10724 {
10725 ERROR3("Path array pointer was NULL");
10726 return FALSE;
10727 }
10728 INT32 NumCoords = pPath->InkPath.GetNumCoords();
10729
10730
10731 if (!(Verbs[NumCoords-1] & PT_CLOSEFIGURE))
10732 {
10733
10734 INT32 SubPathStart = NumCoords-1;
10735 pPath->InkPath.FindStartOfSubPath(&SubPathStart);
10736
10737
10738 if (SubPathStart < (NumCoords-2))
10739 Closeable = (Flags[NumCoords-1].IsSelected || Flags[SubPathStart].IsSelected);
10740 }
10741
10742 return Closeable;
10743 }
10744
10745