#include <extender.h>
Static Public Member Functions | |
static DocRect | CheckValidExtend (NodeRenderableInk *pNode, BYTE fExtendFlags, const DocRect &drTriggerRelation, const DocRect &drTargetRelation, const DocRect &drThisTrigger, const DocRect &drLastTrigger, const DocRect &drLastTarget, BOOL *pOK=NULL, const BOOL ExtendAroundTarget=FALSE) |
This function tests whether or not a call to the extend function will extend an object in a valid way. For example, a path cannot be shrunken so that its control points cross its centre, as this operation is irreversible - if the path was extended back again, these points would extend the wrong direction. Similarly, an invalid extend occurs when a trigger set is shrunk so that its centre happens to move over the centre of a target node which is not moving in this particular extension; undoing this operation would end up dragging the target node back with the trigger. | |
static void | Extend (NodeRenderableInk *pNode, BYTE fExtendFlags, const DocRect &drTriggerRelation, const DocRect &drTargetRelation, const DocRect &drNewTrigger, const DocRect &drLastTrigger, const DocRect &drLastTarget, const DocRect *pdrDifference=NULL, const BOOL ExtendAroundTarget=FALSE, UndoableOperation *pOp=NULL) |
Perform an extend operation on the given Node and its children, using the given rectangles and flags to determine how the Node should transform. | |
static BOOL | ConvertQuickShapesInSelRangeToPaths (UndoableOperation *pUndoOp, Range *pRange) |
Iterates over the given SelRange looking for any NodeRegularShapes, ie QuickShapes. If we find any then they get zapped, and all that is left is a smoking pair of shoes! ... erm, sorry - a NodePath. | |
static BOOL | CheckValidExtend (NodeRenderableInk *pNode, DocRect *pStartRect, DocRect *pEndRect, BYTE fStretchType, DocRect *pOldStartRect=NULL) |
** DEPRECATED - DO NOT CALL ** | |
static void | Extend (NodeRenderableInk *pNode, DocRect *pStartRect, DocRect *pEndRect, BYTE fStretchType, DocRect *pOldStartRect=NULL) |
** DEPRECATED - DO NOT CALL ** | |
static DocRect | ValidateControlPoints (INT32 numPoints, const DocCoord *doccArray, const ExtendParams &ExtParams) |
Validate the given points, using the provided extend parameters. If extending the points is invalid, then return a rectangle containing the largest distances which the points can be shrunk in by. | |
static void | CalculateExtendParams (ExtendParams *pEPS, BYTE fExtendFlags, const DocRect &drTriggerRelation, const DocRect &drTargetRelation, const DocRect &drNewTrigger, const DocRect &drLastTrigger, const DocRect &drLastTarget, const DocRect *pdrDifference=NULL, const BOOL ExtendAroundTarget=FALSE) |
Given the rectangles and flags which define an extension, this function derives the bare information which a Node requires to perform the extension on itself. | |
Private Member Functions | |
CC_DECLARE_MEMDUMP (Extender) | |
Static Private Member Functions | |
static INT32 | CheckInvalidShrinkingPoints (INT32 nCentre, INT32 nDelta, INT32 nOffset, INT32 nNumPoints, const DocCoord *doccArray, BOOL bExamineX) |
Check whether any of the points in the given array will be shrunk past the given limiting value. If all the points check out, we return an all-clear value, which is negative. Otherwise, the maximum safe shrinkage is given. | |
static INT32 | CheckInvalidExpandingPoints (INT32 nCentre, INT32 nDelta, INT32 nOffset, INT32 nNumPoints, const DocCoord *doccArray, BOOL bExamineX) |
Two checks:. | |
static INT32 | CheckLimits (const INT32 limit, const INT32 delta, const INT32 value) |
Checks that the given value may be reduced by the amount delta without going below the given limit value. If it cannot, we return the most which the given value can be safely reduced by. |
Extension is defined as translation of control points, depending on their initial position. All points are moved by the same fixed amount, although the direction* follows the same rules as for stretching - 'x -> x +/- delta'. See also:
Definition at line 203 of file extender.h.
|
Given the rectangles and flags which define an extension, this function derives the bare information which a Node requires to perform the extension on itself.
drTriggerRelation relationship rectangle - the bounding box of the trigger sets when the relationship is defined. drTargetRelation relationship rectangle - the bounding box of the target sets when the relationship is defined. drNewTrigger bounding box of sets of triggers which started the call to this function. drLastTrigger the bounding box of the trigger set(s) before it changed. drLastTarget the bounding box of the target set before it is extended. pdrDifference a rectangle containing four difference parameters which may be used to alter the extend. ok to omit or be NULL.
Definition at line 987 of file extender.cpp. 00992 { 00993 // validate input. 00994 ERROR3IF(pEPS == NULL, "Extender::CalculateExtendParams- pEPS is NULL!"); 00995 00996 // use the relationship rects and the new trigger rect to calculate the new target rect. 00997 DocRect drNewTarget(drNewTrigger); 00998 00999 // x-extend - the new target rect must be x-offset from new-trigger on each 01000 // side, by the same amount as target-relation from trigger-relation. 01001 if (fExtendFlags & X_EXTEND) 01002 { 01003 // if the trigger and target-relation rects do not overlap in the x-direction, 01004 // then the new target rect must be x-offset from new-trigger on its near-side, 01005 // by the same amount as target-relation from trigger-relation. 01006 if (drTargetRelation.lo.x > drTriggerRelation.hi.x) 01007 { 01008 drNewTarget.lo.x = drNewTrigger.hi.x + (drTargetRelation.lo.x - drTriggerRelation.hi.x); 01009 drNewTarget.hi.x = drNewTrigger.hi.x + (drTargetRelation.hi.x - drTriggerRelation.hi.x); 01010 } 01011 else if (drTargetRelation.hi.x < drTriggerRelation.lo.x) 01012 { 01013 drNewTarget.lo.x = drNewTrigger.lo.x - (drTriggerRelation.lo.x - drTargetRelation.lo.x); 01014 drNewTarget.hi.x = drNewTrigger.lo.x - (drTriggerRelation.lo.x - drTargetRelation.hi.x); 01015 } 01016 01017 // normal extend behaviour - distances between corresponding sides are kept constant. 01018 else 01019 { 01020 drNewTarget.lo.x += drTargetRelation.lo.x - drTriggerRelation.lo.x; 01021 drNewTarget.hi.x += drTargetRelation.hi.x - drTriggerRelation.hi.x; 01022 01023 // if the target's new sides are coincident or invalid, then 01024 // they need to be moved back into valid positions. 01025 if (drNewTarget.lo.x >= drNewTarget.hi.x) 01026 { 01027 drNewTarget.hi.x = drNewTarget.lo.x + 2; 01028 } 01029 } 01030 } 01031 else if (fExtendFlags & X_STRETCH) 01032 { 01033 double a = drNewTrigger.Width() / (double)drTriggerRelation.Width(); 01034 INT32 b = drNewTrigger.hi.x - (INT32)(a * drTriggerRelation.hi.x); 01035 01036 drNewTarget.lo.x = b + (INT32)(a * drTargetRelation.lo.x); 01037 drNewTarget.hi.x = b + (INT32)(a * drTargetRelation.hi.x); 01038 } 01039 01040 // y-extend - the new target rect must be y-offset from new-trigger on top and 01041 // bottom, by the same amount as target-relation from trigger-relation. 01042 if (fExtendFlags & Y_EXTEND) 01043 { 01044 // if the trigger and target-relation rects do not overlap in the y-direction, 01045 // then the new target rect must be y-offset from new-trigger on its near-side, 01046 // by the same amount as target-relation from trigger-relation. 01047 if (drTargetRelation.lo.y > drTriggerRelation.hi.y) 01048 { 01049 drNewTarget.lo.y = drNewTrigger.hi.y + (drTargetRelation.lo.y - drTriggerRelation.hi.y); 01050 drNewTarget.hi.y = drNewTrigger.hi.y + (drTargetRelation.hi.y - drTriggerRelation.hi.y); 01051 } 01052 else if (drTargetRelation.hi.y < drTriggerRelation.lo.y) 01053 { 01054 drNewTarget.lo.y = drNewTrigger.lo.y - (drTriggerRelation.lo.y - drTargetRelation.lo.y); 01055 drNewTarget.hi.y = drNewTrigger.lo.y - (drTriggerRelation.lo.y - drTargetRelation.hi.y); 01056 } 01057 01058 // normal extend behaviour - distances between corresponding sides are kept constant. 01059 else 01060 { 01061 drNewTarget.lo.y += drTargetRelation.lo.y - drTriggerRelation.lo.y; 01062 drNewTarget.hi.y += drTargetRelation.hi.y - drTriggerRelation.hi.y; 01063 01064 // if the target's new top and bottom are coincident or invalid, then 01065 // they need to be moved back into valid positions. 01066 if (drNewTarget.lo.y >= drNewTarget.hi.y) 01067 { 01068 drNewTarget.hi.y = drNewTarget.lo.y + 2; 01069 } 01070 } 01071 } 01072 else if (fExtendFlags & Y_STRETCH) 01073 { 01074 double a = drNewTrigger.Height() / (double)drTriggerRelation.Height(); 01075 INT32 b = drNewTrigger.hi.y - (INT32)(a * drTriggerRelation.hi.y); 01076 01077 drNewTarget.lo.y = b + (INT32)(a * drTargetRelation.lo.y); 01078 drNewTarget.hi.y = b + (INT32)(a * drTargetRelation.hi.y); 01079 } 01080 01081 // use the old and new target rectangles to calculate our extension working values. 01082 01083 // extend flags. 01084 pEPS->fExtendFlags = fExtendFlags; 01085 01086 // the start- and end- centres of extension + the offset between them. 01087 // Karim 14/03/2000 - changed to use the trigger set bounds if their old centre 01088 // lies within the bounds of the old target set. 01089 if (!ExtendAroundTarget && drLastTarget.ContainsCoord(drLastTrigger.Centre())) 01090 { 01091 pEPS->doccStartCentre = drLastTrigger.Centre(); 01092 pEPS->doccEndCentre = drNewTrigger.Centre(); 01093 pEPS->doccOffset = pEPS->doccEndCentre - pEPS->doccStartCentre; 01094 } 01095 else 01096 { 01097 pEPS->doccStartCentre = drLastTarget.Centre(); 01098 pEPS->doccEndCentre = drNewTarget.Centre(); 01099 pEPS->doccOffset = pEPS->doccEndCentre - pEPS->doccStartCentre; 01100 } 01101 01102 // magnitudes of extension. note that under extension, objects are first offset 01103 // from start- to end- centre, then extended. this makes extension mirror-symmetric 01104 // so that xinc == xdec (+/- 1). 01105 pEPS->xinc = drNewTarget.hi.x - (drLastTarget.hi.x + pEPS->doccOffset.x); 01106 pEPS->xdec = (drLastTarget.lo.x + pEPS->doccOffset.x) - drNewTarget.lo.x; 01107 pEPS->yinc = drNewTarget.hi.y - (drLastTarget.hi.y + pEPS->doccOffset.y); 01108 pEPS->ydec = (drLastTarget.lo.y + pEPS->doccOffset.y) - drNewTarget.lo.y; 01109 01110 // scale factors, if automatic _stretching_ is required. 01111 pEPS->xscale = drNewTarget.Width() / (double)drLastTarget.Width(); 01112 pEPS->yscale = drNewTarget.Height() / (double)drLastTarget.Height(); 01113 01114 // if our difference rect is non-NULL, then we may need to substitute 01115 // xinc, xdec, yinc, ydec with negative copies of some of its values. 01116 if (pdrDifference != NULL) 01117 { 01118 if (pdrDifference->lo.x != INT32_MAX) pEPS->xdec = -pdrDifference->lo.x; 01119 if (pdrDifference->lo.y != INT32_MAX) pEPS->ydec = -pdrDifference->lo.y; 01120 if (pdrDifference->hi.x != INT32_MAX) pEPS->xinc = -pdrDifference->hi.x; 01121 if (pdrDifference->hi.y != INT32_MAX) pEPS->yinc = -pdrDifference->hi.y; 01122 } 01123 01124 // TODO: should probably not use these, but the equivalent of b (used above) instead. 01125 pEPS->doccScaleStart = drLastTarget.lo; 01126 pEPS->doccScaleEnd = drNewTarget.lo; 01127 01128 // set the various dead-zones; these depend on the signs of the expansions in each dirn. 01129 pEPS->xincExtendBuffer = (pEPS->xinc >= 0) ? EXT_EXPAND_BUFFER : EXT_SHRINK_BUFFER; 01130 pEPS->xdecExtendBuffer = (pEPS->xdec >= 0) ? EXT_EXPAND_BUFFER : EXT_SHRINK_BUFFER; 01131 pEPS->yincExtendBuffer = (pEPS->yinc >= 0) ? EXT_EXPAND_BUFFER : EXT_SHRINK_BUFFER; 01132 pEPS->ydecExtendBuffer = (pEPS->ydec >= 0) ? EXT_EXPAND_BUFFER : EXT_SHRINK_BUFFER; 01133 }
|
|
|
|
Two checks:.
Due to rounding errors, the centre-point of an object depends on whether its width is even or odd. There is a potential for error here, if a point lying one millipoint outside the dead zone is moved out from the centre, and the operation then reversed. If the centre-point changes position due to a new width then the point may be moving back *inside* the dead zone, which will be disallowed -> irreversible operation. This method checks for these points. (boy, what a mouthful!) Assumptions: That the extension being checked is symmetric - ie all points are moving away from the centre point, regardless of their position relative to it.
Definition at line 1174 of file extender.cpp. 01177 { 01178 // return with an all-clear if delta is zero. 01179 if (nDelta == 0) 01180 return -1; 01181 01182 // each point should be offset by nOffset, so instead we 'un-offset' the centre. 01183 // INT32 myCentre = nCentre - nOffset; 01184 01185 /* 01186 * Karim 11/05/2000 01187 * Commented out, as this test is being moved into the actual extension code - rather than 01188 * have invariant points limit the extension, they will have no effect, and will instead 01189 * just not themselves extend. 01190 * 01191 // The test we do is simple - ensure that no points lie within one millipoint of the 01192 // dead zone. We only need one invalid point for the test to fail. 01193 BOOL bPassedTest = TRUE; 01194 if (bExamineX) 01195 { 01196 for (INT32 i = 0; i < nNumPoints && bPassedTest; i ++) 01197 { 01198 bPassedTest = (doccArray[i].x > (myCentre + EXT_EXPAND_BUFFER)) || 01199 (doccArray[i].x < (myCentre - EXT_EXPAND_BUFFER)); 01200 } 01201 } 01202 else 01203 { 01204 for (INT32 i = 0; i < nNumPoints && bPassedTest; i ++) 01205 { 01206 bPassedTest = (doccArray[i].y > (myCentre + EXT_EXPAND_BUFFER)) || 01207 (doccArray[i].y < (myCentre - EXT_EXPAND_BUFFER)); 01208 } 01209 } 01210 01211 return bPassedTest ? -1 : 0; 01212 */ 01213 01214 return -1; 01215 }
|
|
Check whether any of the points in the given array will be shrunk past the given limiting value. If all the points check out, we return an all-clear value, which is negative. Otherwise, the maximum safe shrinkage is given.
Definition at line 824 of file extender.cpp. 00827 { 00828 // return with an all-clear if delta is zero. 00829 if (nDelta == 0) 00830 return -1; 00831 00832 // test the points we were given, and determine the furthest we can move them without 00833 // dragging any into the dead zone, defined as the limit value +/- our buffer size. 00834 // this value will be the least of all the maximum distances that each point can 00835 // shrink by. 00836 INT32 maxShrink, smallest_maxShrink = INT32_MAX; 00837 00838 // each point should be offset by nOffset so for testing, we 'un-offset' the centre. 00839 INT32 myCentre = nCentre - nOffset; 00840 00841 // nDelta < 0 means we are being dragged down or left. 00842 // we're checking that each point can stretch by nDelta down towards nCentre. 00843 // if it can't, we see how far it _can_ go. 00844 if (nDelta < 0) 00845 { 00846 // validate the x-component of the coordinates. 00847 if (bExamineX) 00848 { 00849 for (INT32 i = 0; i < nNumPoints; i ++) 00850 { 00851 maxShrink = CheckLimits(myCentre, nDelta, doccArray[i].x); 00852 if (maxShrink >= 0 && smallest_maxShrink > maxShrink) 00853 smallest_maxShrink = maxShrink; 00854 } 00855 } 00856 00857 // validate the y-component of the coordinates. 00858 else 00859 { 00860 for (INT32 i = 0; i < nNumPoints; i ++) 00861 { 00862 maxShrink = CheckLimits(myCentre, nDelta, doccArray[i].y); 00863 if (maxShrink >= 0 && smallest_maxShrink > maxShrink) 00864 smallest_maxShrink = maxShrink; 00865 } 00866 } 00867 } 00868 00869 // nDelta > 0 means we are being dragged up or right. 00870 // we're checking that each point can stretch by nDelta up towards nCentre. 00871 // if it can't, we see how far it _can_ go. 00872 else 00873 { 00874 // validate the x-component of the coordinates. 00875 if (bExamineX) 00876 { 00877 for (INT32 i = 0; i < nNumPoints; i ++) 00878 { 00879 maxShrink = CheckLimits(myCentre, -nDelta, myCentre - doccArray[i].x + myCentre); 00880 if (maxShrink >= 0 && smallest_maxShrink > maxShrink) 00881 smallest_maxShrink = maxShrink; 00882 } 00883 } 00884 00885 // validate the y-component of the coordinates. 00886 else 00887 { 00888 for (INT32 i = 0; i < nNumPoints; i ++) 00889 { 00890 maxShrink = CheckLimits(myCentre, -nDelta, myCentre - doccArray[i].y + myCentre); 00891 if (maxShrink >= 0 && smallest_maxShrink > maxShrink) 00892 smallest_maxShrink = maxShrink; 00893 } 00894 } 00895 } 00896 00897 return smallest_maxShrink == INT32_MAX ? -1 : smallest_maxShrink; 00898 }
|
|
Checks that the given value may be reduced by the amount delta without going below the given limit value. If it cannot, we return the most which the given value can be safely reduced by.
Definition at line 930 of file extender.cpp. 00931 { 00932 // data validation. 00933 ERROR3IF(delta >= 0, "Extender::CheckLimits called with delta non-negative!"); 00934 00935 // we return an all-clear if the test value starts in the buffer zone. 00936 if (value >= limit - EXT_SHRINK_BUFFER && value <= limit + EXT_SHRINK_BUFFER) 00937 return -1; 00938 00939 // give the all-clear if the test value lies below the limit value already. 00940 // also give the all-clear if the test value will not be drawn down into the dead-zone. 00941 if (value < limit - EXT_SHRINK_BUFFER || value + delta > limit + EXT_SHRINK_BUFFER) 00942 return -1; 00943 00944 // ok, we're invalid - return the safe shrinkage distance for the test value. 00945 return value - (limit + EXT_SHRINK_BUFFER + 1); 00946 }
|
|
** DEPRECATED - DO NOT CALL **
Definition at line 186 of file extender.cpp. 00191 { 00192 ERROR2( FALSE, 00193 "This implementation of Extender::CheckValidExtend is no longer used or valid" ); 00194 }
|
|
This function tests whether or not a call to the extend function will extend an object in a valid way. For example, a path cannot be shrunken so that its control points cross its centre, as this operation is irreversible - if the path was extended back again, these points would extend the wrong direction. Similarly, an invalid extend occurs when a trigger set is shrunk so that its centre happens to move over the centre of a target node which is not moving in this particular extension; undoing this operation would end up dragging the target node back with the trigger.
drTriggerRelation relationship rectangle - the bounding box of the trigger sets when the relationship is defined. drTargetRelation relationship rectangle - the bounding box of the target sets when the relationship is defined. drNewTrigger bounding box of sets of triggers which started the call to this function. drLastTrigger the bounding box of the trigger set(s) before it changed. drLastTarget the bounding box of the target set before it is extended. This function should always be called on all objects sharing the same name, before* Extender::Extend is called to actually perform the extension on those objects, to make sure that no irreversible operation is performed.
NOTE: A call to Extender::CheckValidExtend must *always* be made before performing a corresponding Extender::Extend process. Definition at line 436 of file extender.cpp. 00440 { 00441 // validate parameters. 00442 ERROR2IF( pNode == NULL, DocRect(0, 0, 0, 0), 00443 "NULL parameters passed to Extender::CheckValidExtend" ); 00444 00445 ERROR2IF( ((fExtendFlags & X_EXTEND) && (fExtendFlags & X_STRETCH)) || 00446 ((fExtendFlags & Y_EXTEND) && (fExtendFlags & Y_STRETCH)), 00447 DocRect(0, 0, 0, 0), 00448 "Extender::CheckValidExtend called with contradictory flags in fExtendFlags" ); 00449 00450 if (pOK) 00451 *pOK = TRUE; 00452 // quit immediately if any of the bounding rectangles is invalid, 00453 // or is of zero width or height. 00454 if( !drTriggerRelation.IsValid() || 00455 !drTargetRelation.IsValid() || 00456 !drNewTrigger.IsValid() || 00457 !drLastTrigger.IsValid() || 00458 !drLastTarget.IsValid() || 00459 drTriggerRelation.Height() == 0 || 00460 drTriggerRelation.Width() == 0 || 00461 drTargetRelation.Height() == 0 || 00462 drTargetRelation.Width() == 0 || 00463 drNewTrigger.Height() == 0 || 00464 drNewTrigger.Width() == 0 || 00465 drLastTrigger.Height() == 0 || 00466 drLastTrigger.Width() == 0 || 00467 drLastTarget.Height() == 0 || 00468 drLastTarget.Width() == 0) 00469 { 00470 if (pOK) 00471 *pOK = FALSE; 00472 00473 return DocRect(0, 0, 0, 0); 00474 } 00475 00476 00477 00478 // determine extension working values. 00479 ExtendParams eps; 00480 CalculateExtendParams( &eps, fExtendFlags, drTriggerRelation, drTargetRelation, 00481 drNewTrigger, drLastTrigger, drLastTarget, NULL, ExtendAroundTarget ); 00482 00483 // check whether pNode, or any child of pNode, is extendible. 00484 // also, check that extending all of these Nodes is a valid operation. 00485 // if this is the case, recursively extend pNode and its children. 00486 DocRect drMinExtend = pNode->ValidateExtend(eps); 00487 BOOL bValidExtend = ( drMinExtend.lo.x == INT32_MAX && 00488 drMinExtend.lo.y == INT32_MAX && 00489 drMinExtend.hi.x == INT32_MAX && 00490 drMinExtend.hi.y == INT32_MAX ); 00491 00492 // DEBUG: 00493 #ifdef _DEBUG 00494 TRACEUSER( "Karim", _T("%5s ValidateExtend() on %s\n"), bValidExtend ? _T("TRUE") : _T("FALSE"), 00495 pNode->Name()); 00496 #endif 00497 00498 BOOL bExtendible = TRUE; 00499 00500 if (!bExtendible || !bValidExtend) 00501 { 00502 //#ifdef _DEBUG 00503 // TRACEUSER( "Karim", _T("Invalid Extend on %s; Ext: %d, Valid: %d\n"), 00504 // pNode->Name(), bExtendible, bValidExtend); 00505 //#endif 00506 return drMinExtend; 00507 } 00508 00509 // return the outcome of the test, in the form of drMinExtend. 00510 return drMinExtend; 00511 }
|
|
Iterates over the given SelRange looking for any NodeRegularShapes, ie QuickShapes. If we find any then they get zapped, and all that is left is a smoking pair of shoes! ... erm, sorry - a NodePath. Notes: This is all done undoably. There is however a problem in that we do not necessarily want to completely unwind the UndoOp we were given if anything goes wrong. But if we don't do that then what _can_ we do??? Currently, if things go wrong while converting to shapes, we just try to convert as many shapes to paths as possible and return FALSE at the end. We don't mind if pSel is empty or has no QuickShapes. Our search of the SelRange is deep - we look at children of nodes in the range too.
Definition at line 235 of file extender.cpp. 00237 { 00238 // validate params. 00239 ERROR2IF(pUndoOp == NULL || pRange == NULL, FALSE, "Invalid parameter(s)"); 00240 00241 // TODO: May need to set the range's RangeControl to avoid promoting to parents. 00242 00243 // iterate over the range and build a list of QuickShapes. 00244 // we do a depth-first search from every node in the range, 00245 // looking everywhere for those those pesky QuickShapes :) 00246 BOOL bQuickShapesConverted = FALSE; 00247 std::list<NodeRegularShape*> lpShapes; 00248 Node* pCurrentRangeNode = pRange->FindFirst(); 00249 while (pCurrentRangeNode != NULL) 00250 { 00251 Node* pNextNode = NULL; 00252 Node* pCurrentNode = pCurrentRangeNode->FindFirstDepthFirst(); 00253 while (pCurrentNode != NULL) 00254 { 00255 pNextNode = pCurrentNode->FindNextDepthFirst(pCurrentRangeNode); 00256 if (pCurrentNode->IsARegularShape()) 00257 { 00258 if (!(pCurrentNode->FindParent (CC_RUNTIME_CLASS (NodeBlend)))) 00259 { 00260 // note thate we're *saying* we're going to replace with only one node. 00261 // this isn't necessarily true - DoBecomeA on a brushed path results in 00262 // many ungrouped nodes. it's just the best we can do, considering blends. 00263 ObjChangeFlags ocf; 00264 ocf.ReplaceNode = TRUE; 00265 ObjChangeParam ObjChange(OBJCHANGE_STARTING, ocf, pCurrentNode, pUndoOp); 00266 if (pCurrentNode->AllowOp(&ObjChange, FALSE, FALSE)) 00267 lpShapes.push_front((NodeRegularShape*)pCurrentNode); 00268 } 00269 /*else 00270 { 00271 // note thate we're *saying* we're going to replace with only one node. 00272 // this isn't necessarily true - DoBecomeA on a brushed path results in 00273 // many ungrouped nodes. it's just the best we can do, considering blends. 00274 ObjChangeFlags ocf; 00275 ocf.ReplaceNode = TRUE; 00276 ObjChangeParam ObjChange(OBJCHANGE_STARTING, ocf, pCurrentNode, pUndoOp); 00277 if (pCurrentNode->AllowOp(&ObjChange, TRUE, FALSE)) 00278 lpShapes.push_front((NodeRegularShape*)pCurrentNode); 00279 }*/ 00280 } 00281 pCurrentNode = pNextNode; 00282 } 00283 pCurrentRangeNode = pRange->FindNext(pCurrentRangeNode, TRUE); 00284 } 00285 00286 // okay, if our list isn't empty then we have work to do. 00287 if (!lpShapes.empty()) 00288 { 00289 // invalidate the region of the selection. 00290 if (pUndoOp->DoInvalidateNodesRegions(*pRange, TRUE)) 00291 { 00292 // change all the QuickShapes into NodePaths. 00293 NodeRegularShape* pCurrentShape = NULL; 00294 while (!lpShapes.empty()) 00295 { 00296 pCurrentShape = lpShapes.front(); 00297 lpShapes.pop_front(); 00298 BecomeA BecomeAPath( BECOMEA_REPLACE, 00299 CC_RUNTIME_CLASS(NodePath), 00300 pUndoOp, 00301 pCurrentShape->IsSelected() ); 00302 00303 if (pCurrentShape->CanBecomeA(&BecomeAPath)) 00304 { 00305 if (!(pCurrentShape->FindParent (CC_RUNTIME_CLASS (NodeBlend)))) 00306 { 00307 if (pCurrentShape->DoBecomeA(&BecomeAPath)) 00308 { 00309 pCurrentShape->DeSelect(FALSE); 00310 bQuickShapesConverted = TRUE; 00311 } 00312 } 00313 /*else 00314 { 00315 NodeBlend* ptrBlend = (NodeBlend*) pCurrentShape->FindParent (CC_RUNTIME_CLASS (NodeBlend)); 00316 BecomeA BecomeAPath( BECOMEA_REPLACE, 00317 CC_RUNTIME_CLASS(NodePath), 00318 pUndoOp, 00319 pCurrentShape->IsSelected() ); 00320 if (pCurrentShape->DoBecomeA(&BecomeAPath)) 00321 { 00322 pCurrentShape->DeSelect(FALSE); 00323 bQuickShapesConverted = TRUE; 00324 } 00325 00326 // nastiness - to reinitialise the blend, I need a ptr to the converted path 00327 // BUT there is no easy way of doing this! This is a hack - which seems to 00328 // hold up well .... NOTE: assumes that the last action executed was a 00329 // HideNodeAction (i.e. hide pCurrentShape) 00330 00331 ActionList* actList = pUndoOp->GetUndoActionList (); // get undo history 00332 ListItem* pItem = actList->GetTail (); // get last op 00333 ERROR3IF (!IS_A (pItem, HideNodeAction), "Assumed HideNodeAction is not a HideNodeAction!"); 00334 HideNodeAction* hnAct = (HideNodeAction*) pItem; 00335 NodeRenderableInk* newNode = (NodeRenderableInk*) hnAct->GetNode (); 00336 ERROR3IF (!IS_A (ptrBlend, NodeBlend), "NodeBlend is not a NodeBlend!"); 00337 00338 BOOL done = FALSE; 00339 NodeBlender* ptrNode = ptrBlend->FindFirstBlender (); 00340 00341 while (!done) 00342 { 00343 ptrNode->Deinit (); 00344 00345 if (ptrNode->GetNodeStart () == pCurrentShape) 00346 { 00347 ptrNode->Reinit(newNode, NULL, FALSE); 00348 } 00349 if (ptrNode->GetNodeEnd () == pCurrentShape) 00350 { 00351 ptrNode->Reinit(NULL, newNode, FALSE); 00352 } 00353 00354 ptrNode = ptrBlend->FindNextBlender (ptrNode); 00355 00356 if (!ptrNode) 00357 { 00358 done = TRUE; 00359 } 00360 } 00361 }*/ 00362 } 00363 } 00364 } 00365 if (bQuickShapesConverted) 00366 pRange->Update(); 00367 } 00368 00369 return bQuickShapesConverted; 00370 }
|
|
** DEPRECATED - DO NOT CALL **
Definition at line 157 of file extender.cpp. 00162 { 00163 ERROR2RAW("This implementation of Extender::Extend is no longer used or valid"); 00164 }
|
|
Perform an extend operation on the given Node and its children, using the given rectangles and flags to determine how the Node should transform.
drTriggerRelation relationship rectangle - the bounding box of the trigger sets when the relationship is defined. drTargetRelation relationship rectangle - the bounding box of the target sets when the relationship is defined. drNewTrigger bounding box of sets of triggers which started the call to this function. drLastTrigger the bounding box of the trigger set(s) before it changed. drLastTarget the bounding box of the target set before it is extended. pdrDifference a rectangle containing four difference parameters which may be used to alter the extend. ok to omit or be NULL.
NOTE: A call to Extender::CheckValidExtend must always be made before performing a corresponding Extender::Extend process. Definition at line 560 of file extender.cpp. 00565 { 00566 // validate parameters. 00567 if (pNode == NULL) 00568 { 00569 ERROR2RAW("NULL parameters passed to Extender::Extend."); 00570 return; 00571 } 00572 00573 if (((fExtendFlags & X_EXTEND) && (fExtendFlags & X_STRETCH)) || 00574 ((fExtendFlags & Y_EXTEND) && (fExtendFlags & Y_STRETCH))) 00575 { 00576 ERROR2RAW("Extender::Extend called with contradictory flags in fExtendFlags"); 00577 return; 00578 } 00579 00580 // quit immediately if any of the bounding rectangles is invalid, 00581 // or is of zero width or height. 00582 if (!drTriggerRelation.IsValid() || 00583 !drTargetRelation.IsValid() || 00584 !drNewTrigger.IsValid() || 00585 !drLastTrigger.IsValid() || 00586 !drLastTarget.IsValid() || 00587 drTriggerRelation.Height() == 0 || 00588 drTriggerRelation.Width() == 0 || 00589 drTargetRelation.Height() == 0 || 00590 drTargetRelation.Width() == 0 || 00591 drNewTrigger.Height() == 0 || 00592 drNewTrigger.Width() == 0 || 00593 drLastTrigger.Height() == 0 || 00594 drLastTrigger.Width() == 0 || 00595 drLastTarget.Height() == 0 || 00596 drLastTarget.Width() == 0) 00597 { 00598 ERROR2RAW("Extender::Extend; Invalid or zero-width rectangle"); 00599 return; 00600 } 00601 00602 // determine extension working values. 00603 ExtendParams eps; 00604 eps.pOp = pOp; 00605 CalculateExtendParams( &eps, fExtendFlags, drTriggerRelation, drTargetRelation, 00606 drNewTrigger, drLastTrigger, 00607 drLastTarget, pdrDifference, ExtendAroundTarget ); 00608 00609 // this hasn't really changed size so do nothing 00610 if (!eps.xdec && !eps.xinc && !eps.ydec && !eps.yinc && eps.xscale == 1.0 && eps.yscale == 1.0 00611 && eps.doccOffset.x == 0 && eps.doccOffset.y == 0) 00612 return; 00613 00614 // invalidate the old image of the object, perform the extension 00615 // and flag that the object should be redrawn. 00616 // we must look above this node, to detect whether we are the child 00617 // of a node whose on-screen bounds are greater than ours. 00618 // if this is the case, we need to invalidate *that* node and 00619 // get it to redraw. 00620 // TODO: there may be a better way of doing this (is it necessary at all with the AllowOp mechanism?) 00621 BOOL bFoundBigParent = FALSE; 00622 Node* pInvalidateNode = pNode->FindParent(); 00623 while (pInvalidateNode != NULL && !IS_A(pInvalidateNode, Layer) && !bFoundBigParent) 00624 { 00625 if (IS_A(pInvalidateNode, NodeBevelController) || 00626 IS_A(pInvalidateNode, NodeShadowController) || 00627 IS_A(pInvalidateNode, NodeContourController)) 00628 bFoundBigParent = TRUE; 00629 else 00630 pInvalidateNode = pInvalidateNode->FindParent(); 00631 } 00632 00633 if (!bFoundBigParent) 00634 pInvalidateNode = pNode; 00635 00636 ((NodeRenderableInk*)pInvalidateNode)->RedrawObject(); 00637 ((NodeRenderableInk*)pInvalidateNode)->InvalidateBoundingRect(); 00638 pNode->Extend(eps); 00639 00640 // DEBUG: 00641 //#ifdef _DEBUG 00642 // TRACEUSER( "Karim", _T("Extend() on %s\n"), pNode->Name()); 00643 //#endif 00644 00645 ((NodeRenderableInk*)pInvalidateNode)->RedrawObject(); 00646 }
|
|
Validate the given points, using the provided extend parameters. If extending the points is invalid, then return a rectangle containing the largest distances which the points can be shrunk in by.
If shrinking in a particular direction is ok, the corresponding DocRect value will be set to INT32_MAX.
Definition at line 677 of file extender.cpp. 00678 { 00679 // validate data 00680 ERROR3IF(doccArray == NULL, "Extender::ValidateControlPoints- NULL doccArray passed!"); 00681 00682 DocRect drMaxSafeShrink(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX), drCheckExtend; 00683 00684 // this check is only necessary if extension will be occurring along an 00685 // axis; if the extension type is stretch, or no action, no validation 00686 // is required. 00687 00688 // for each of the four directions of displacement, and only if we shrank, check that 00689 // none of the points lie in a position to which they would not be returned under the 00690 // inverse extend operation. if they do, we record the largest safe amount we could 00691 // shrink them in by. 00692 00693 // providing the extend operation involves displacing all points by the difference 00694 // between start- and end- centres, followed by the extension, these invalid points 00695 // will be only those which would be dragged inwards, to cross over the end-centre. 00696 00697 if (ExtParams.fExtendFlags & X_EXTEND) 00698 { 00699 if (ExtParams.xinc < 0) 00700 { 00701 INT32 minXshrink = CheckInvalidShrinkingPoints( ExtParams.doccEndCentre.x, 00702 ExtParams.xinc, 00703 ExtParams.doccOffset.x, 00704 numPoints, doccArray, TRUE ); 00705 if (minXshrink >= 0) // invalid, so record the return value. 00706 drMaxSafeShrink.hi.x = minXshrink; 00707 } 00708 00709 // we do a different test if we're expanding. 00710 else if (ExtParams.xinc > 0) 00711 { 00712 INT32 minXshrink = CheckInvalidExpandingPoints( ExtParams.doccEndCentre.x, 00713 ExtParams.xinc, 00714 ExtParams.doccOffset.x, 00715 numPoints, doccArray, TRUE ); 00716 if (minXshrink >= 0) // invalid, so record the return value. 00717 drMaxSafeShrink.hi.x = minXshrink; 00718 } 00719 00720 if (ExtParams.xdec < 0) 00721 { 00722 INT32 minXshrink = CheckInvalidShrinkingPoints( ExtParams.doccEndCentre.x, 00723 -ExtParams.xdec, 00724 ExtParams.doccOffset.x, 00725 numPoints, doccArray, TRUE ); 00726 if (minXshrink >= 0) // invalid, so record the return value. 00727 drMaxSafeShrink.lo.x = minXshrink; 00728 } 00729 00730 // we do a different test if we're expanding. 00731 else if (ExtParams.xdec > 0) 00732 { 00733 INT32 minXshrink = CheckInvalidExpandingPoints( ExtParams.doccEndCentre.x, 00734 -ExtParams.xdec, 00735 ExtParams.doccOffset.x, 00736 numPoints, doccArray, TRUE ); 00737 if (minXshrink >= 0) // invalid, so record the return value. 00738 drMaxSafeShrink.lo.x = minXshrink; 00739 } 00740 } 00741 00742 if (ExtParams.fExtendFlags & Y_EXTEND) 00743 { 00744 if (ExtParams.yinc < 0) 00745 { 00746 INT32 minYshrink = CheckInvalidShrinkingPoints( ExtParams.doccEndCentre.y, 00747 ExtParams.yinc, 00748 ExtParams.doccOffset.y, 00749 numPoints, doccArray, FALSE ); 00750 if (minYshrink >= 0) // invalid, so record the return value. 00751 drMaxSafeShrink.hi.y = minYshrink; 00752 } 00753 00754 // we do a different test if we're expanding. 00755 else if (ExtParams.yinc > 0) 00756 { 00757 INT32 minYshrink = CheckInvalidExpandingPoints( ExtParams.doccEndCentre.y, 00758 ExtParams.yinc, 00759 ExtParams.doccOffset.y, 00760 numPoints, doccArray, FALSE ); 00761 if (minYshrink >= 0) // invalid, so record the return value. 00762 drMaxSafeShrink.hi.y = minYshrink; 00763 } 00764 00765 if (ExtParams.ydec < 0) 00766 { 00767 INT32 minYshrink = CheckInvalidShrinkingPoints( ExtParams.doccEndCentre.y, 00768 -ExtParams.ydec, 00769 ExtParams.doccOffset.y, 00770 numPoints, doccArray, FALSE ); 00771 if (minYshrink >= 0) // invalid, so record the return value. 00772 drMaxSafeShrink.lo.y = minYshrink; 00773 } 00774 00775 // we do a different test if we're expanding. 00776 else if (ExtParams.ydec > 0) 00777 { 00778 INT32 minYshrink = CheckInvalidExpandingPoints( ExtParams.doccEndCentre.y, 00779 -ExtParams.ydec, 00780 ExtParams.doccOffset.y, 00781 numPoints, doccArray, FALSE ); 00782 if (minYshrink >= 0) // invalid, so record the return value. 00783 drMaxSafeShrink.lo.y = minYshrink; 00784 } 00785 } 00786 00787 return drMaxSafeShrink; 00788 }
|