#include <pathedit.h>
Inheritance diagram for OpDeletePoints:
Public Member Functions | |
OpDeletePoints () | |
OpDeletePoints constructor. | |
void | Do (OpDescriptor *) |
Performs the Delete point(s) operation. | |
Static Public Member Functions | |
static BOOL | Init () |
OpDeletePoints initialiser method. | |
static OpState | GetState (String_256 *, OpDescriptor *) |
For finding the OpDeletePoints's state. | |
Private Member Functions | |
BOOL | DeleteLineTo (NodePath *pPath, INT32 Index, BOOL *PathExists) |
This is called by OpDeletePoints::Do in order to delete a PT_LINETO endpoint from a path. | |
BOOL | DeleteMoveTo (NodePath *pPath, INT32 Index, BOOL *PathExists) |
This is called by OpDeletePoints::Do in order to delete a PT_MOVETO endpoint from a path. | |
BOOL | DeleteBezierTo (NodePath *pPath, INT32 Index, BOOL *PathExists) |
This is called by OpDeletePoints::Do in order to delete a PT_BEZIERTO endpoint from a path. | |
Static Private Member Functions | |
static BOOL | WillDeleteEntirePath (NodePath *pPath) |
Sees if some of the path will remain after a delete points operation. | |
static BOOL | TryDeleteLineTo (NodePath *pPath, INT32 Index, BOOL *PathExists) |
This is called by OpDeletePoints::WillDeletePath in order to delete a PT_LINETO endpoint from a path. | |
static BOOL | TryDeleteMoveTo (NodePath *pPath, INT32 Index, BOOL *PathExists) |
This is called by OpDeletePoints::WillDeletePath in order to delete a PT_MOVETO endpoint from a path. | |
static BOOL | TryDeleteBezierTo (NodePath *pPath, INT32 Index, BOOL *PathExists) |
This is called by OpDeletePoints::WillDeletePath in order to delete a PT_BEZIERTO endpoint from a path. |
Definition at line 590 of file pathedit.h.
|
OpDeletePoints constructor.
Definition at line 6613 of file pathedit.cpp. 06613 : SelOperation() 06614 { 06615 }
|
|
This is called by OpDeletePoints::Do in order to delete a PT_BEZIERTO endpoint from a path.
Definition at line 7255 of file pathedit.cpp. 07256 { 07257 PathVerb* Verbs = pPath->InkPath.GetVerbArray(); 07258 // PathFlags* Flags = pPath->InkPath.GetFlagArray(); 07259 // DocCoord* Coords = pPath->InkPath.GetCoordArray(); 07260 INT32 NumCoords = pPath->InkPath.GetNumCoords(); 07261 PathFlags TempFlags; 07262 DocCoord EndPoint; 07263 07264 // See if this is the end of the path 07265 if (Index+1 != NumCoords) 07266 { 07267 // See what the next element is 07268 switch (Verbs[Index+1] & ~ PT_CLOSEFIGURE) 07269 { 07270 case PT_LINETO: 07271 // A curve followed by a line. Just delete the curve. 07272 return DoDeletePathSection(pPath, Index-2, 3); 07273 break; 07274 case PT_BEZIERTO: 07275 // A curve followed by a curve. First delete the second control point, 07276 // the endpoint, and the first control point of the next (curve) element 07277 // Then we should smooth it somehow (later) 07278 return DoDeletePathSection(pPath, Index-1, 3); 07279 break; 07280 case PT_MOVETO: 07281 // Tricky again, the next point is a MoveTo, so we have to check all the special 07282 // cases like closed paths, paths with single elements, etc. 07283 if (Verbs[Index] & PT_CLOSEFIGURE) 07284 { 07285 // The path is closed, it's fiddle time again (see above) 07286 // For now, deselect it 07287 return DoChangeSelection(pPath, Index, FALSE); 07288 } 07289 else 07290 { 07291 // At least the path isn't closed. We might safely be able to delete this 07292 // section, as long as the previous element isn't a MoveTo, in which case 07293 // we have to delete the whole subpath 07294 if (Verbs[Index-3] == PT_MOVETO) 07295 { 07296 // Delete the whole subpath 07297 return DoDeletePathSection(pPath, Index-3, 4); 07298 } 07299 else 07300 { 07301 // Only delete the curve section 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 // This is the case when we're at the end of the path 07313 // Is the path a closed one 07314 if (Verbs[Index] & PT_CLOSEFIGURE) 07315 { 07316 // the path is closed. This is still tricky (see above and above) 07317 // so trick that I'll just deselect it 07318 return DoChangeSelection(pPath, Index, FALSE); 07319 } 07320 else 07321 { 07322 // The path isn't closed, so check for this being the only element in 07323 // the path 07324 if (Verbs[Index-3] == PT_MOVETO) 07325 { 07326 // Either this could be one of many subpaths, or the only subpath 07327 if (NumCoords == 4) 07328 { 07329 // This is the only subpath, it only has one element, so delete 07330 // the whole path 07331 *PathExists = FALSE; 07332 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE)); 07333 } 07334 else 07335 { 07336 // There are other subpaths, so just delete this one 07337 return DoDeletePathSection(pPath, Index-3, 4); 07338 } 07339 } 07340 else 07341 { 07342 // It's not the only element in the path so delete it 07343 return DoDeletePathSection(pPath, Index-2, 3); 07344 } 07345 } 07346 } 07347 }
|
|
This is called by OpDeletePoints::Do in order to delete a PT_LINETO endpoint from a path.
Definition at line 6882 of file pathedit.cpp. 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 // work differently depending on if this is the last point in the path 06893 if (Index+1 != NumCoords) 06894 { 06895 // See what the next element is 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 // for a line next to a bezier, delete the bezier segment 06903 // and change the line coordinate to go to the end of the bezier 06904 EndPoint = Coords[Index+3]; // Get coords of bez endpt 06905 TempVerb = Verbs[Index]; 06906 TempFlags = Flags[Index]; 06907 TempFlags.IsSelected = Flags[Index+3].IsSelected; 06908 06909 // Change the LineTo element to go to the old end pos of the bezier 06910 // setting the selection status of the new point 06911 // Delete whole bezier section 06912 return (DoAlterPathElement(pPath, Index, EndPoint, TempFlags, TempVerb) 06913 && DoDeletePathSection(pPath, Index+1, 3)); 06914 break; 06915 case PT_MOVETO: 06916 // Next point is a MoveTo so this is the last point in a subpath 06917 // See if the path is closed 06918 if (Verbs[Index] & PT_CLOSEFIGURE) 06919 { 06920 // The subpath is closed, so do something clever (see below) 06921 // As a temporary measure to prevent an infinite loop we'll 06922 // deselect this point 06923 return DoChangeSelection(pPath, Index, FALSE) ; 06924 } 06925 else 06926 { 06927 // This subpath is open, so we either just delete the element 06928 // or if the previous element is a MoveTo, we delete that as well 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 // Here, the point being deleted is the last point in the path 06942 // See if the path is being closed 06943 if (Verbs[Index] & PT_CLOSEFIGURE) 06944 { 06945 // We're deleting the last point of a closed path. HELP! 06946 // This entails deleting the corresponding MoveTo as well 06947 // Which is quite complicated. I'll do that in a minute. 06948 // For now, I'll just clear selection 06949 return DoChangeSelection(pPath, Index, FALSE); 06950 } 06951 else 06952 { 06953 // This is an open path, so the only worry is if this is the only 06954 // line element in the path 06955 if (Verbs[Index-1] == PT_MOVETO) 06956 { 06957 // Two possiblilities here, either this is the only path, or 06958 // it's part of a subpath. 06959 06960 if (NumCoords == 2) 06961 { 06962 // This is the only path, so delete the whole node 06963 *PathExists = FALSE; 06964 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE)) ; 06965 } 06966 else 06967 { 06968 // It's not the only subpath, so just delete these two elements 06969 return DoDeletePathSection(pPath, Index-1, 2); 06970 } 06971 } 06972 else 06973 { 06974 // It's not the only element in the subpath, so just delete it 06975 return DoDeletePathSection(pPath, Index, 1); 06976 } 06977 } 06978 } 06979 }
|
|
This is called by OpDeletePoints::Do in order to delete a PT_MOVETO endpoint from a path.
Definition at line 7000 of file pathedit.cpp. 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 // I think this is slightly simpler than all the others (except for closed) 07010 // First see if this subpath is closed 07011 if (pPath->InkPath.IsSubPathClosed(Index)) 07012 { 07013 // Great, the path is closed, so I'll have to do all sorts of difficult things 07014 // (yet again, see above) 07015 // or just deselect it, whichever's easier 07016 if (!DoChangeSelection(pPath, Index, FALSE)) 07017 return FALSE; 07018 07019 // Right, time to bite the bullet and do this. 07020 // This is actually the only occasion when this type of point can be 07021 // deleted - when a path is closed, the endpoint cannot be selected 07022 // without the start point being selected, so we only have to cope with 07023 // this situation and ensure that we clear the selection bits 07024 // on the corresponding endpoints 07025 07026 INT32 EndIndex = Index; 07027 pPath->InkPath.FindEndOfSubPath(&EndIndex); 07028 07029 // There are situations where we have got a two element path, a MoveTo, then either 07030 // a LineTo or a BezierTo. We must deal with the case of both endpoints being 07031 // selected and remove the entire sub-path. 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 // What we have to do here is find the last element, and the first element, 07052 // delete one of them (probably the first one but it might depend on what 07053 // type of point they are) 07054 07055 // Now EndIndex tells us where the end element is 07056 // Let's see what the two elements are 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 // Both beziers. What we do here is remember the second 07063 // control point of the first bezier, as well as the endpoint, 07064 // then change the second control point and the endpoint 07065 // of the last bezier accordingly 07066 if ( ! (DoAlterPathElement(pPath, EndIndex+1, Coords[Index+2], Flags[Index+2], Verbs[Index+2]) && 07067 // Alter the endpoint, keeping the same verb but changing the other elements 07068 DoAlterPathElement(pPath, EndIndex+2, Coords[Index+3], Flags[Index+3], Verbs[EndIndex+2]) && 07069 // Now alter the MoveTo coordinates 07070 DoAlterPathElement(pPath, Index, Coords[Index+3], Flags[Index], Verbs[Index]) && 07071 // And now delete the first curve element altogether 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 // When one element is a line, we always keep the line 07082 // In this case, we have to change the coords of the 07083 // moveto to be the same as the start of the final section, 07084 // then delete the final section 07085 if ( ! (DoAlterPathElement(pPath, Index, Coords[EndIndex-1], Flags[Index], Verbs[Index]) && 07086 // Alter the element previous to the curve to have the close bit set 07087 DoAlterPathElement(pPath, EndIndex-1, Coords[EndIndex-1], Flags[EndIndex-1], Verbs[EndIndex-1] | PT_CLOSEFIGURE) && 07088 // And delete the curve section 07089 DoDeletePathSection(pPath, EndIndex, 3) 07090 ) ) 07091 { 07092 return FALSE; 07093 } 07094 } 07095 else if (StartVerb == PT_BEZIERTO && EndVerb == PT_LINETO) 07096 { 07097 // Similar to the previous case, except the lineto is at the end 07098 // What we do here is set the lineto coord and the moveto coord 07099 // to the the endpoint of the first (curve) element, making sure the 07100 // lineto selection bit is clear. 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 // Now delete the curve element 07105 DoDeletePathSection(pPath, Index+1, 3) 07106 ) ) 07107 { 07108 return FALSE; 07109 } 07110 } 07111 else 07112 { 07113 // start and end must be linetos 07114 // Alter the final lineto and the moveto to have the coords of 07115 // the end of the first lineto 07116 if ( ! (DoAlterPathElement(pPath, Index, Coords[Index+1], Flags[Index], Verbs[Index]) && 07117 DoAlterPathElement(pPath, EndIndex, Coords[Index+1], Flags[EndIndex], Verbs[EndIndex]) && 07118 // make sure the endpoint isn't selected 07119 DoChangeSelection(pPath, EndIndex, Flags[Index+1].IsSelected) && 07120 // delete the first lineto 07121 DoDeletePathSection(pPath, Index+1, 1) 07122 ) ) 07123 { 07124 return FALSE; 07125 } 07126 } 07127 07128 // Now recache the pointers 07129 Coords = pPath->InkPath.GetCoordArray(); 07130 Verbs = pPath->InkPath.GetVerbArray(); 07131 Flags = pPath->InkPath.GetFlagArray(); 07132 07133 // The last thing I have to do is check the selected status of the new endpoint 07134 // and select the MoveTo if it is selected, and deselect the moveto otherwise 07135 // Index is still valid for the start of the path 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 // Change the selection of the MoveTo to match the selection 07145 // of the endpoint in this closed path 07146 return DoChangeSelection(pPath, Index, IsSelected); 07147 } 07148 else 07149 { 07150 // The path isn't closed. 07151 // Are we looking at the start of a curve or a line? 07152 if ((Verbs[Index+1] & ~ PT_CLOSEFIGURE) == PT_BEZIERTO) 07153 { 07154 // We're deleting this bezier segment. We have to check if this is a lone element 07155 if (Index+4 == NumCoords || Verbs[Index+4] == PT_MOVETO) 07156 { 07157 // It's a lone element, so either delete the subpath or delete the whole node 07158 if (NumCoords == 4) 07159 { 07160 // It's all there is in the path, so delete the whole thing 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 // It's not a lone element, so delete the curveto, and change the MoveTo 07172 // so that it now moves to the endpoint of the curve 07173 EndPoint = Coords[Index+3]; 07174 07175 // Look at the selected bit of the end of the curve, and copy that 07176 // to the moveto, in case that point wanted deleting as well 07177 BOOL WasSelected = Flags[Index+3].IsSelected; 07178 07179 // Delete the section containing the curve 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 // Alter the MoveTo element so coords and flags are correct 07187 return DoAlterPathElement(pPath, Index, EndPoint, TempFlags, TempVerb); 07188 } 07189 } 07190 else 07191 { 07192 // Since we can't have a moveto following a moveto, the next element 07193 // has to be a path (let's check that with an ENSURE) 07194 ERROR2IF(((Verbs[Index+1] & ~PT_CLOSEFIGURE) != PT_LINETO), FALSE, "Badly formed path in DeletePoint"); 07195 07196 // Check if it's a single element 07197 if (Index+2 == NumCoords || Verbs[Index+2] == PT_MOVETO) 07198 { 07199 // It's a lone element so either delete the subpath or the whole path 07200 // See if this is the only subpath 07201 if (NumCoords == 2) 07202 { 07203 // This is the only element in the path, so hide the whole node 07204 *PathExists = FALSE; 07205 return (DoInvalidateNodeRegion(pPath,TRUE,TRUE) && DoHideNode(pPath, TRUE)) ; 07206 } 07207 else 07208 { 07209 // Just delete this subpath 07210 return DoDeletePathSection(pPath, Index, 2); 07211 } 07212 } 07213 else 07214 { 07215 // There is another element after this, so delete the line element 07216 // and alter the Moveto element so that it goes to where the endpoint 07217 // used to go 07218 EndPoint = Coords[Index+1]; 07219 07220 // Look at the selected bit of the line element 07221 BOOL WasSelected = Flags[Index+1].IsSelected; 07222 07223 // Delete the section containing the line 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 // Alter the MoveTo so that it goes to the position of the lineto, and it's selected 07231 // if necessary 07232 return DoAlterPathElement(pPath, Index, EndPoint, TempFlags, TempVerb); 07233 } 07234 } 07235 } 07236 }
|
|
Performs the Delete point(s) operation.
Reimplemented from Operation. Definition at line 6720 of file pathedit.cpp. 06721 { 06722 // Obtain the current selections 06723 SelRange* Selected = GetApplication()->FindSelection(); 06724 Node* pNode = Selected->FindFirst(); 06725 06726 BOOL ok = DoStartSelOp(TRUE,TRUE); 06727 06728 // We need to ask the effected nodes if they (and their parents) can handle this node being deleted 06729 ObjChangeFlags cFlags/*(TRUE)*/; 06730 cFlags.TransformNode = TRUE; 06731 ObjChangeParam ObjDelete(OBJCHANGE_STARTING,ObjChangeFlags(TRUE),NULL,this); 06732 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); 06733 06734 // loop through the selection 06735 while (pNode != NULL) 06736 { 06737 // First see where the next node is, in case this one gets deleted 06738 Node* NextNode = Selected->FindNext(pNode); 06739 06740 // Is the node of interest? 06741 // we're only interested in NodePaths which have selected points, and that will allow this op to happen 06742 BOOL DoThisPath = (IS_A(pNode, NodePath) || IS_A(pNode,NodeBlendPath)) && ((NodePath*)pNode)->InkPath.IsSubSelection(); 06743 06744 // Check with the path and it's parents 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 // Do the delete if required 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 // Record the bounds and do a redraw 06767 ok = RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath) != AC_FAIL ; 06768 06769 // // Store the sub-selection state of the path 06770 // if (ok) 06771 // ok = (StorePathSubSelStateAction::DoRecord(this, &UndoActions, &ThisPath->InkPath) != AC_FAIL); 06772 06773 // Simply hide all the path if all of it is to be deleted 06774 if (WillDelete) 06775 { 06776 if (ok) 06777 ok = DoHideNode(pNode, TRUE); 06778 PathStillExists = FALSE; 06779 } 06780 06781 // We have to delete every selected endpoint in the path (if it still exists) 06782 while (ok && PathStillExists && ThisPath->InkPath.IsSubSelection()) 06783 { 06784 // First refresh the pointers to the arrays 06785 ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); 06786 NumCoords = ThisPath->InkPath.GetNumCoords(); 06787 06788 // Scan for a selected endpoint 06789 INT32 i; 06790 for ( i =0;i<NumCoords && (!Flags[i].IsSelected || !Flags[i].IsEndPoint);i++) 06791 ; // ; deliberate 06792 06793 // Now, either i == NumCoords or it points at a selected endpoint 06794 // if i == NumCoords there weren't any selected endpoints, so clear 06795 // the selected bits on random control points 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 // i indexes into a selected endpoint, which is the one we have to delete. 06806 // Are we looking at a MoveTo, CurveTo or a LineTo? 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 // now that we have deleted every selected point on the path we need to check to see if we are 06823 // left with a closed path consisting of a moveto followed by a single line or a curve. 06824 // if we are then we should delete the node. 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 // Having finished deleting, record the bounds of the new path 06835 // This is the partner to the RecalcBoundsAction at the start of this Op 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 // Update all the parents of this node 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 }
|
|
For finding the OpDeletePoints's state.
Definition at line 6654 of file pathedit.cpp. 06655 { 06656 // Look at the current selection 06657 SelRange* Selected = GetApplication()->FindSelection(); 06658 Node* pNode = Selected->FindFirst(); 06659 06660 // We need to ask the effected nodes if they (and their parents) can handle this node being deleted 06661 ObjChangeParam ObjDelete(OBJCHANGE_STARTING, ObjChangeFlags(TRUE), NULL, NULL); 06662 ObjChangeParam ObjChange(OBJCHANGE_STARTING, ObjChangeFlags(), NULL, NULL); 06663 06664 // Go through the selection until we find a selected point 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 // See if this will delete the node or not 06673 BOOL WillHide = WillDeleteEntirePath((NodePath*)pNode); 06674 06675 // Check that we can do this op of the node 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 // We've found at least one node we can act upon 06685 FoundSelected = TRUE; 06686 break; 06687 } 06688 } 06689 06690 } 06691 pNode = Selected->FindNext(pNode); 06692 } 06693 06694 OpState OpSt; 06695 // The operation is disabled if there are no complex paths selected 06696 if (!FoundSelected) 06697 { 06698 OpSt.Greyed = TRUE; 06699 *UIDescription = String_256(_R(IDS_NEEDS_SELECTED_POINT)); 06700 } 06701 06702 return(OpSt); 06703 }
|
|
OpDeletePoints initialiser method.
Reimplemented from SimpleCCObject. Definition at line 6632 of file pathedit.cpp. 06633 { 06634 BTNOP( DELETEPOINTSOP, OpDeletePoints, EDIT) 06635 return TRUE; 06636 }
|
|
This is called by OpDeletePoints::WillDeletePath in order to delete a PT_BEZIERTO endpoint from a path.
Definition at line 7752 of file pathedit.cpp. 07753 { 07754 PathVerb* Verbs = pPath->InkPath.GetVerbArray(); 07755 PathFlags* Flags = pPath->InkPath.GetFlagArray(); 07756 // DocCoord* Coords = pPath->InkPath.GetCoordArray(); 07757 INT32 NumCoords = pPath->InkPath.GetNumCoords(); 07758 PathFlags TempFlags; 07759 DocCoord EndPoint; 07760 07761 // See if this is the end of the path 07762 if (Index+1 != NumCoords) 07763 { 07764 // See what the next element is 07765 switch (Verbs[Index+1] & ~PT_CLOSEFIGURE) 07766 { 07767 case PT_LINETO: 07768 // A curve followed by a line. Just delete the curve. 07769 return pPath->InkPath.DeleteSection(Index-2, 3); 07770 break; 07771 case PT_BEZIERTO: 07772 // A curve followed by a curve. First delete the second control point, 07773 // the endpoint, and the first control point of the next (curve) element 07774 return pPath->InkPath.DeleteSection(Index-1, 3); 07775 break; 07776 case PT_MOVETO: 07777 // Tricky again, the next point is a MoveTo, so we have to check all the special 07778 // cases like closed paths, paths with single elements, etc. 07779 if (Verbs[Index] & PT_CLOSEFIGURE) 07780 { 07781 // The path is closed, For now, deselect it 07782 Flags[Index].IsSelected = FALSE; 07783 return TRUE; 07784 } 07785 else 07786 { 07787 // We might safely be able to delete this 07788 // section, as long as the previous element isn't a MoveTo, in which case 07789 // we have to delete the whole subpath 07790 if (Verbs[Index-3] == PT_MOVETO) 07791 { 07792 // Delete the whole subpath 07793 return pPath->InkPath.DeleteSection(Index-3, 4); 07794 } 07795 else 07796 { 07797 // Only delete the curve section 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 // This is the case when we're at the end of the path 07809 if (Verbs[Index] & PT_CLOSEFIGURE) 07810 { 07811 // the path is closed. This is still tricky (see above and above) 07812 Flags[Index].IsSelected = FALSE; 07813 return TRUE; 07814 } 07815 else 07816 { 07817 // The path isn't closed, so check for this being the only element in the path 07818 if (Verbs[Index-3] == PT_MOVETO) 07819 { 07820 // Either this could be one of many subpaths, or the only subpath 07821 if (NumCoords == 4) 07822 { 07823 *PathExists = FALSE; 07824 return TRUE; 07825 } 07826 else 07827 { 07828 // There are other subpaths, so just delete this one 07829 return pPath->InkPath.DeleteSection(Index-3, 4); 07830 } 07831 } 07832 else 07833 { 07834 // It's not the only element in the path so delete it 07835 return pPath->InkPath.DeleteSection(Index-2, 3); 07836 } 07837 } 07838 } 07839 }
|
|
This is called by OpDeletePoints::WillDeletePath in order to delete a PT_LINETO endpoint from a path.
Definition at line 7456 of file pathedit.cpp. 07457 { 07458 // Get the path pointers 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 // work differently depending on if this is the last point in the path 07466 if (Index+1 != NumCoords) 07467 { 07468 // See what the next element is 07469 switch (Verbs[Index+1] & ~PT_CLOSEFIGURE) 07470 { 07471 case PT_LINETO: 07472 // Delete the current line, createing a line from Index-1 to Index +1 07473 return (pPath->InkPath.DeleteSection(Index, 1)); 07474 break; 07475 case PT_BEZIERTO: 07476 // Delete the folloing curve, creating a line from Index-1 to Index+3 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 // Next point is a MoveTo so this is the last point in a subpath 07483 if (Verbs[Index] & PT_CLOSEFIGURE) 07484 { 07485 // Subpath is closed, leave it it to the next moveto 07486 Flags[Index].IsSelected = FALSE; 07487 return TRUE; 07488 } 07489 else 07490 { 07491 // This subpath is open, so we either just delete the element 07492 // or if the previous element is a MoveTo, we delete that as well 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 // Here, the point being deleted is the last point in the path 07506 // See if the path is closed 07507 if (Verbs[Index] & PT_CLOSEFIGURE) 07508 { 07509 // Just deselect the last point 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 // This is the only path, so delete the whole node 07520 *PathExists = FALSE; 07521 return TRUE; 07522 } 07523 else 07524 { 07525 // It's not the only subpath, so just delete these two elements 07526 return (pPath->InkPath.DeleteSection(Index-1, 2)); 07527 } 07528 } 07529 else 07530 { 07531 // It's not the only element in the subpath, so just delete it 07532 return (pPath->InkPath.DeleteSection(Index, 1)); 07533 } 07534 } 07535 } 07536 }
|
|
This is called by OpDeletePoints::WillDeletePath in order to delete a PT_MOVETO endpoint from a path.
Definition at line 7554 of file pathedit.cpp. 07555 { 07556 // Get the path pointers 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 // See if this subpath is closed 07564 if (pPath->InkPath.IsSubPathClosed(Index)) 07565 { 07566 // Deselect it 07567 Flags[Index].IsSelected = FALSE; 07568 07569 // Get the index of the other end of the subpath 07570 INT32 EndIndex = Index; 07571 pPath->InkPath.FindEndOfSubPath(&EndIndex); 07572 07573 // There are situations where we have got a two element path, a MoveTo, then either 07574 // a LineTo or a BezierTo. We must deal with the case of both endpoints being 07575 // selected and remove the entire sub-path. 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 // Now EndIndex tells us where the end element is 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 // Both beziers. What we do here is remember the second 07602 // control point of the first bezier, as well as the endpoint, 07603 // then change the second control point and the endpoint 07604 // of the last bezier accordingly 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 // When one element is a line, we always keep the line 07619 // In this case, we have to change the coords of the 07620 // moveto to be the same as the start of the final section, 07621 // then delete the final section 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 // Similar to the previous case, except the lineto is at the end 07633 // What we do here is set the lineto coord and the moveto coord 07634 // to the the endpoint of the first (curve) element, making sure the 07635 // lineto selection bit is clear. 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 // start and end must be linetos 07647 // Alter the final lineto and the moveto to have the coords of 07648 // the end of the first lineto 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 // Recache the pointers 07659 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); 07660 07661 // The last thing I have to do is check the selected status of the new endpoint 07662 // and select the MoveTo if it is selected, and deselect the moveto otherwise 07663 // Index is still valid for the start of the path 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 // Change the selection of the MoveTo to match the selection 07673 // of the endpoint in this closed path 07674 Flags[Index].IsSelected = IsSelected; 07675 } 07676 else 07677 { 07678 // The path isn't closed. 07679 // Are we looking at the start of a curve or a line? 07680 if ((Verbs[Index+1] & ~ PT_CLOSEFIGURE) == PT_BEZIERTO) 07681 { 07682 // We're deleting this bezier segment. We have to check if this is a lone element 07683 if (Index+4 == NumCoords || Verbs[Index+4] == PT_MOVETO) 07684 { 07685 // It's a lone element, so either delete the subpath or delete the whole node 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 // Since we can't have a moveto following a moveto, the next element 07705 // has to be a path (let's check that with an ENSURE) 07706 ERROR2IF(((Verbs[Index+1] & ~PT_CLOSEFIGURE) != PT_LINETO), FALSE, "Badly formed path in DeletePoint"); 07707 07708 // Check if it's a single element 07709 if (Index+2 == NumCoords || Verbs[Index+2] == PT_MOVETO) 07710 { 07711 // It's a lone element so either delete the subpath or the whole path 07712 // See if this is the only subpath 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 // There is another element after this, so delete the line element 07724 // and alter the Moveto element so that it goes to where the endpoint 07725 // used to go 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 }
|
|
Sees if some of the path will remain after a delete points operation.
Definition at line 7364 of file pathedit.cpp. 07365 { 07366 // If the path has no selected endpoints then it won't be deleted 07367 if (!pTreePath->InkPath.IsSubSelection()) 07368 return FALSE; 07369 07370 // Get the path pointers; 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 // We need to scan all the endpoints. If there are ALL selected then we can 07379 // just delete the whole path. 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 // Make a copy of the path before testing the delete 07392 NodePath* pPath = (NodePath*)pTreePath->SimpleCopy(); 07393 if (pPath == NULL) 07394 return FALSE; 07395 07396 // We have to delete every selected endpoint in the path 07397 while (PathStillExists) 07398 { 07399 // First refresh the pointers to the arrays 07400 NumCoords = pPath->InkPath.GetNumCoords(); 07401 pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); 07402 07403 // Scan for a selected endpoint 07404 INT32 i; 07405 for ( i =0;i<NumCoords && (!Flags[i].IsSelected || !Flags[i].IsEndPoint);i++) 07406 ; // ; deliberate 07407 07408 // break out if we didn't find an endpoint 07409 if (i == NumCoords) 07410 break; 07411 07412 // i indexes into a selected endpoint which we have to delete. 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 // now that we have deleted every selected point on the path we need to check 07430 // the path to see if is still valid 07431 if (PathStillExists) 07432 PathStillExists = pPath->IsPathAllowable(); 07433 07434 delete pPath; 07435 07436 return !PathStillExists; 07437 }
|