opscale.cpp

Go to the documentation of this file.
00001 // $Id: opscale.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // Operation for doing an interactive scale of the selection
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "opscale.h"
00105 
00106 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "rik.h"
00108 #include "selector.h"
00109 //#include "clikdrag.h"
00110 
00111 // This is not compulsory, but you may as well put it in so that the correct version
00112 // of your file can be registered in the .exe
00113 DECLARE_SOURCE("$Revision: 1282 $");
00114 
00115 // An implement to match the Declare in the .h file.
00116 // If you have many classes, it is recommended to place them all together, here at the start of the file
00117 CC_IMPLEMENT_DYNCREATE(OpScaleTrans, TransOperation)
00118 
00119 // This will get Camelot to display the filename and linenumber of any memory allocations
00120 // that are not released at program exit
00121 #define new CAM_DEBUG_NEW
00122 
00123 
00124 
00125 
00126 
00127 /********************************************************************************************
00128 
00129 >   OpScaleTrans::OpScaleTrans()
00130 
00131     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00132     Created:    20/7/93
00133     Purpose:    Constructor. Does nothing.
00134 
00135 ********************************************************************************************/
00136 
00137 OpScaleTrans::OpScaleTrans(): TransOperation()
00138 {
00139     StatusHelpID = _R(IDS_SCALETRANS_STATUS1);
00140     StatusHelpID2 = _R(IDS_SCALETRANS_STATUS2);
00141 }
00142 
00143 
00144 
00145 
00146 
00147 /********************************************************************************************
00148 >   virtual void OpScaleTrans::InitTransformImmediate(OpParam* pParam)
00149 
00150     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00151     Created:    4/11/94
00152     Inputs:     pParam      ---     pointer an OpParam whose Param2 member is a pointer
00153                                     to two FIXED16's that represent the scale factor for
00154                                     the width and height of the selction.
00155     Outputs:    -
00156     Returns:    -
00157     Purpose:    
00158     Errors:     -
00159     SeeAlso:    -
00160 ********************************************************************************************/
00161 
00162 void OpScaleTrans::InitTransformImmediate(OpParam* pParam)
00163 {
00164 
00165     FIXED16* pfx = (FIXED16*) PVOID(pParam->Param2);
00166     XScaleFactor = *pfx;
00167     YScaleFactor = *(pfx + 1);
00168 
00169 
00170     if (XScaleFactor == 0)
00171         XScaleFactor = 1.0;
00172 
00173     if (YScaleFactor == 0)
00174         YScaleFactor = 1.0;
00175 
00176 }
00177 
00178 
00179 
00180 
00181 
00182 
00183 /********************************************************************************************
00184 
00185 >   virtual void OpScaleTrans::InitTransformOnDrag(DocCoord PointerPos, ClickModifiers ClickMods)
00186 
00187     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00188     Created:    19/7/94
00189     Inputs:     PointerPos - The position of the mouse at the start of the drag
00190                 ClickMods - the keyboard modifiers that were active at the start of the drag
00191     Purpose:    Sets up the parameters needed to build the transform matrix at the start
00192                 of the drag. This base class version of this function does nothing.
00193 
00194 ********************************************************************************************/
00195 
00196 void OpScaleTrans::InitTransformOnDrag(DocCoord PointerPos, ClickModifiers ClickMods)
00197 {
00198     // WEBSTER - markn 14/2/97
00199     // Rewritten so it will work when "snap to the grid" is on
00200 
00201     // Note the pointer pos at the beginning of the drag
00202     PointerStart.x = PointerPos.x;
00203     PointerStart.y = PointerPos.y;
00204 
00205     // Note the width & height of the original bounds - used to calc scale factors
00206     UnitWidth  = BoundingData.Width;
00207     UnitHeight = BoundingData.Height;
00208 
00209     // Work out which x point of the bounds to take, based on the blob that was clicked on
00210     switch (StartBlob)
00211     {
00212         case 3:
00213         case 8: BoundsStartPoint.x = BoundingData.x + BoundingData.Width;
00214                 break;
00215         case 1:
00216         case 6: BoundsStartPoint.x = BoundingData.x;
00217                 UnitWidth = -UnitWidth;                 // if low x, then we need -ve x scale factors
00218                 break;
00219 
00220         default: ERROR3("Unrecognised blob values"); break;
00221     }
00222 
00223     // Work out which x point of the bounds to take, based on the blob that was clicked on
00224     switch (StartBlob)
00225     {
00226         case 1:
00227         case 3: BoundsStartPoint.y = BoundingData.y + BoundingData.Height;
00228                 break;
00229         case 6:
00230         case 8: BoundsStartPoint.y = BoundingData.y;
00231                 UnitHeight = -UnitHeight;               // if low y, then we need -ve y scale factors
00232                 break;
00233 
00234         default: ERROR3("Unrecognised blob values"); break;
00235     }
00236 
00237     // Make sure that they are not zero
00238     if (UnitWidth==0)   UnitWidth = 1;
00239     if (UnitHeight==0)  UnitHeight = 1;
00240 
00241     // Set the scale factors to 1 (ie no scale)
00242     XScaleFactor = FIXED16(1);
00243     YScaleFactor = FIXED16(1);
00244 }
00245 
00246 
00247 
00248 
00249 /********************************************************************************************
00250 
00251 >   virtual void OpScaleTrans::UpdateTransformOnDrag(DocCoord PointerPos, Spread*, ClickModifiers&)
00252 
00253     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00254     Created:    19/7/94
00255     Inputs:     PointerPos - The latest position of the mouse
00256                 Spread* - The spread the mouse is over
00257                 ClickModifiers - The click modifiers in place now
00258     Purpose:    Does the calculations needed when the mouse moves to keep all the params
00259                 needed to build the rotation matrix up to date.
00260 
00261 ********************************************************************************************/
00262 
00263 void OpScaleTrans::UpdateTransformOnDrag(DocCoord PointerPos, Spread* pClickSpread, ClickModifiers& ClickMods)
00264 {
00265     // Make sure that the cursor does not wrap around at the edge of spreads
00266     if (pClickSpread != StartSpread)
00267         PointerPos = MakeRelativeToSpread(StartSpread, pClickSpread, PointerPos);
00268 
00269     // Snap the pointer position
00270     if (!ClickMods.Constrain)
00271         DocView::SnapSelected(pClickSpread, &PointerPos, FALSE, TRUE);
00272 
00273     // If the Adjust key is down then we should adjust the Unit sizes to compensate
00274     // for the moving centre of transform
00275     INT32 WorkingHeight = UnitHeight;
00276     INT32 WorkingWidth = UnitWidth;
00277 
00278     // if Adjust is being used, adjust the height and width so that scaling still works
00279     if (ClickMods.Adjust)
00280     {
00281         WorkingHeight /= 2;
00282         WorkingWidth /= 2;
00283     }
00284 
00285     // WEBSTER - markn 14/2/97
00286     // Rewritten so it will work when "snap to the grid" is on
00287 
00288     // Work out how far the pointer has moved compared with the initial pointer pos
00289     INT32 pdx = PointerPos.x - PointerStart.x;
00290     INT32 pdy = PointerPos.y - PointerStart.y;
00291 
00292     // Move the bounds point by the distance the mouse pointer has moved and
00293     // calc the snapped version of the new bounds pos
00294     DocCoord SnappedBoundsPoint(BoundsStartPoint.x + pdx,BoundsStartPoint.y + pdy);
00295 
00296     if (!ClickMods.Constrain)
00297         DocView::SnapSelected(StartSpread, &SnappedBoundsPoint, FALSE, TRUE);
00298 
00299     // Calc the proportion the bounds have changed compared with the original working dimensions
00300     INT32 dx = (SnappedBoundsPoint.x - BoundsStartPoint.x) + WorkingWidth;
00301     INT32 dy = (SnappedBoundsPoint.y - BoundsStartPoint.y) + WorkingHeight;
00302 
00303     // Calc the scale factors as a fraction of the change between the origin & scaled dimensions
00304     XScaleFactor = FIXED16(double(dx) / double(WorkingWidth));
00305     YScaleFactor = FIXED16(double(dy) / double(WorkingHeight));
00306 
00307     // Deal with the aspect ratio being locked
00308     if (LockAspect)
00309     {
00310         // If the aspect ratio is locked, X and Y should be the same.
00311         // Always take the greatest scale factor. 
00312         // But be careful to retain the sign of the scale factors - only make their
00313         // magnitudes equal! (Sorry about the yucky implementation of this!)
00314         if (YScaleFactor > XScaleFactor)
00315         {
00316             FIXED16 AbsY = (YScaleFactor < 0 ? -YScaleFactor : YScaleFactor);
00317             XScaleFactor = (XScaleFactor < 0 ? -AbsY : AbsY);
00318         }
00319         else
00320         {
00321             FIXED16 AbsX = (XScaleFactor < 0 ? -XScaleFactor : XScaleFactor);
00322             YScaleFactor = (YScaleFactor < 0 ? -AbsX : AbsX);
00323         }
00324     }
00325 
00326     // Deal with constrain.
00327     // Constrain scale factors to be whole numbers.
00328     // This has to be done here instead of overriding the ConstrainDrag function.
00329     if (ClickMods.Constrain)
00330     {
00331         // Constrained squash forces scale to whole number multiple of original size...
00332         FIXED16 Sign;
00333 
00334         Sign = (XScaleFactor<0 ? -1 : 1);           // Compute sign of pure scale
00335         XScaleFactor+=FIXED16((double)0.5);         // Round scale to nearest integer
00336         XScaleFactor = XScaleFactor.MakeShort();
00337         if (XScaleFactor==0) XScaleFactor = Sign;   // Prevent scale from being zero by setting
00338                                                     // it to +/- 1 depending on sign of pure scale.
00339         Sign = (YScaleFactor<0 ? -1 : 1);
00340         YScaleFactor+=FIXED16((double)0.5);
00341         YScaleFactor = YScaleFactor.MakeShort();
00342         if (YScaleFactor==0) YScaleFactor = Sign;
00343     }
00344 
00345     // Update information for the user...
00346     // Must update x,y,w,h,scale and possible angle.
00347     BoundingData.XScale = XScaleFactor;
00348     BoundingData.YScale = YScaleFactor;
00349     BoundingData.ScaleChanged = TRUE;
00350     // See also UpdateTransformBoundingData function in this file...
00351 }
00352 
00353 
00354 
00355 /********************************************************************************************
00356 
00357 >   void OpScaleTrans::BuildMatrix()
00358 
00359     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00360     Created:    19/7/94
00361     Purpose:    Builds the transform matrix required to rotate the selection about the
00362                 point CentreOfRot by the required number of degrees
00363 
00364 ********************************************************************************************/
00365 
00366 void OpScaleTrans::BuildMatrix()
00367 {
00368     // Build a matrix to scale by the correct amount and one to translate back from the origin
00369     Matrix ScaleBy(XScaleFactor, YScaleFactor);
00370     Matrix TransFromOrigin(CentreOfTrans.x, CentreOfTrans.y);
00371 
00372     // First translate the centre of scaling to the origin, then scale, then translate back
00373     Transform = Matrix(-CentreOfTrans.x, -CentreOfTrans.y);
00374     Transform *= ScaleBy;
00375     Transform *= TransFromOrigin;
00376 }
00377 
00378 
00379 
00380 
00381 
00382 /********************************************************************************************
00383 
00384 >   virtual void OpScaleTrans::ConstrainDrag(DocCoord* PointerPos)
00385 
00386     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00387     Created:    19/7/94
00388     Inputs:     PointerPos - The current position of the mouse that needs to be constrained
00389     Outputs:    PointerPos - The position of the mouse after it has been constrained
00390     Purpose:    Will constrain the mouse position to lie along rays from the centre of
00391                 rotation at the constrain angle apart (45 degrees by default)
00392 
00393 ********************************************************************************************/
00394 
00395 void OpScaleTrans::ConstrainDrag(DocCoord* PointerPos)
00396 {
00397     // Constrain the mouse movement to hoizontal, vertical or diagonal
00398     DocView::ConstrainToAngle(CentreOfTrans, PointerPos);
00399 }
00400 
00401 
00402 /********************************************************************************************
00403 
00404 >   BOOL OpScaleTrans::Declare()
00405 
00406     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00407     Created:    5/7/93
00408     Returns:    TRUE if all went OK, False otherwise
00409     Purpose:    Adds the operation to the list of all known operations
00410 
00411 ********************************************************************************************/
00412 
00413 BOOL OpScaleTrans::Declare()
00414 {
00415     return (RegisterOpDescriptor(0, _R(IDS_SCALETRANS), CC_RUNTIME_CLASS(OpScaleTrans),
00416                                 OPTOKEN_SCALE, TransOperation::GetState)); 
00417 }
00418 
00419 
00420 
00421 /********************************************************************************************
00422 
00423 >   void OpScaleTrans::UpdateTransformBoundingData()
00424 
00425     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00426     Created:    04/9/94
00427     Purpose:    Override the base class version of this fn to ensure that new bounds
00428                 are calculated and placed in the BoundingData structure.
00429 
00430 ********************************************************************************************/
00431 
00432 void OpScaleTrans::UpdateTransformBoundingData()
00433 {
00434 #ifndef STANDALONE
00435     if (pSelTool != NULL)
00436     {
00437 
00438         ComputeNewBounds();
00439         // Tell the tool about the current transform bounding data
00440         pSelTool->DragMove(&BoundingData);
00441     }
00442 #endif
00443 }
00444 
00445 
00446 
00447 
00448 /********************************************************************************************
00449 
00450 >   FIXED16 OpScaleTrans::GetScalar()
00451 
00452     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00453     Created:    09/01/2004
00454     Returns:    FIXED16 value of the equivalent scale factor for the transform.
00455     Purpose:    Returns the Transforms idea of the equivalent scale factor for the transform.
00456                 This is mainly used to help with the scaling of line widths to save them
00457                 trying to extract the scale factor from the matrix.
00458 
00459 ********************************************************************************************/
00460 
00461 FIXED16 OpScaleTrans::GetScalar()
00462 {
00463     // Just return the current value of the scale factor
00464     return YScaleFactor;
00465 }

Generated on Sat Nov 10 03:47:49 2007 for Camelot by  doxygen 1.4.4