arrows.cpp

Go to the documentation of this file.
00001 // $Id: arrows.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 // Defines ArrowRec class (a Line ArrowHead Record)
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 //#include "arrows.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "doccoord.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "fixed16.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "gdraw.h"
00110 #include "grndrgn.h"            // for REAL_GDRAW
00111 
00112 //#include "will2.h"
00113 
00114 DECLARE_SOURCE("$Revision: 1282 $");
00115 
00116 CC_IMPLEMENT_DYNCREATE(ArrowRec, CCObject)
00117 
00118 // Declare smart memory handling in Debug builds
00119 #define new CAM_DEBUG_NEW
00120 
00121 const INT32 ZEROWIDTH_ARROW_LINEWIDTH = (72000/64);
00122 
00123 /********************************************************************************************
00124 
00125 >   ArrowRec::ArrowRec()
00126 
00127     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00128     Created:    4/4/95
00129     Purpose:    Default constructor for Arrow Record class.
00130                 Create a NULL Arrow Record.
00131     SeeAlso:    -
00132 
00133 ********************************************************************************************/
00134 
00135 ArrowRec::ArrowRec()
00136 {
00137     ArrowShape  = NULL;
00138     Centre      = DocCoord(0,0);
00139 
00140     LineWidth   = DEFAULT_ARROW_LINEWIDTH;
00141     ArrowWidth  = 3;
00142     ArrowHeight = 3;
00143 
00144     StartArrow = FALSE;
00145     ScaleWithLineWidth = TRUE;
00146     ArrowID = 0;
00147 
00148     m_bExtendPath = TRUE;
00149 
00150     IsNull = TRUE;
00151 }
00152 
00153 /********************************************************************************************
00154 
00155 >   ArrowRec::ArrowRec(Path* pArrowPath, const DocCoord& ArrowCentre, 
00156                        INT32 LineWidth = DEFAULT_ARROW_LINEWIDTH, 
00157                        FIXED16 WidthScale = 1, FIXED16 HeightScale = 1)
00158 
00159     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00160     Created:    4/4/95
00161 
00162     Inputs:     pArrowPath  - The Path describing the shape of the ArrowHead.
00163                 Centre      - The arrowhead centre (relative to the path coords).
00164                 LineWidth   - The line width that the Arrow head was designed for.
00165                 WidthScale  - The amount to scale the Arrow Width by (ie. Aspect Ratio)
00166                 HeightScale - The amount to scale the Arrow Height by (ie. Aspect Ratio)
00167 
00168     Purpose:    Constructor for Arrow Record class.
00169     Errors:     -
00170     SeeAlso:    -
00171 
00172 ********************************************************************************************/
00173 
00174 ArrowRec::ArrowRec(Path* pArrowPath, const DocCoord& ArrowCentre, 
00175                    INT32 ArrowLineWidth, 
00176                    FIXED16 ArrowWidthScale, FIXED16 ArrowHeightScale,
00177                    BOOL Start)
00178 {
00179     ArrowShape  = pArrowPath;
00180     Centre      = ArrowCentre;
00181 
00182     LineWidth   = ArrowLineWidth;
00183     ArrowWidth  = ArrowWidthScale;
00184     ArrowHeight = ArrowHeightScale;
00185 
00186     StartArrow = Start;
00187 
00188     ScaleWithLineWidth = TRUE;
00189     ArrowID = -1;
00190 
00191     m_bExtendPath = TRUE;
00192 
00193     IsNull = FALSE;
00194 }
00195 
00196 /********************************************************************************************
00197 
00198 >   ArrowRec::ArrowRec(ArrowRec& OtherArrow)
00199 
00200     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00201     Created:    4/4/95
00202     Purpose:    Copy constructor for Arrows.
00203                 Makes an ArrowHead identical to the specified one.
00204     SeeAlso:    -
00205 
00206 ********************************************************************************************/
00207 
00208 ArrowRec::ArrowRec(const ArrowRec& OtherArrow)
00209 {
00210     *this = OtherArrow;
00211 }
00212 
00213 /********************************************************************************************
00214 
00215 >   ArrowRec::~ArrowRec()
00216 
00217     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00218     Created:    4/4/95
00219     Purpose:    Destructor for Arrow Record class.
00220                 Deletes the arrow path.
00221     SeeAlso:    -
00222 
00223 ********************************************************************************************/
00224 
00225 ArrowRec::~ArrowRec()
00226 {
00227     if (ArrowShape != NULL)
00228         delete ArrowShape;
00229 }
00230 
00231 /********************************************************************************************
00232 
00233 >   BOOL ArrowRec::CreateStockArrow(StockArrow ArrowType)
00234 
00235     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00236     Created:    4/4/95
00237     Inputs:     ArrowType - The StockArrow number of the ArrowHead to create.
00238     Returns:    FALSE, if failed to create the arrow path.
00239     Purpose:    Constructs a Stock ArrowHead.
00240     Errors:     Out of Memory.
00241     SeeAlso:    StockArrow
00242 
00243 ********************************************************************************************/
00244 
00245 BOOL ArrowRec::CreateStockArrow(StockArrow ArrowType)
00246 {
00247     if (ArrowShape != NULL)
00248     {
00249         delete ArrowShape;
00250         ArrowShape = NULL;
00251     }
00252 
00253     BOOL ok;
00254     Path* pPath;
00255 
00256     const INT32 Size  = 3;
00257     const INT32 Width = (72000/2)*3;
00258 
00259     if (ArrowType >= NUM_STOCK_ARROWS)
00260         ArrowType = SA_STRAIGHTARROW;
00261 
00262     // Set the ArrowID
00263     ArrowID = ArrowType;
00264 
00265     switch (ArrowType)
00266     {
00267         case SA_STRAIGHTARROW:
00268 
00269             /*
00270             STRAIGHT
00271             -9 54 m
00272             -9 0 l
00273             -9 -54 l
00274             117 0 l
00275             -9 54 l
00276             -9 54 l
00277             */
00278 
00279             pPath = new Path();
00280             if (pPath == NULL)
00281                 return FALSE;
00282 
00283             ok = pPath->Initialise(4);
00284             if (ok)      pPath->FindStartOfPath();
00285             if (ok) ok = pPath->InsertMoveTo(DocCoord( -9000,  54000));
00286             if (ok) ok = pPath->InsertLineTo(DocCoord( -9000, -54000));
00287             if (ok) ok = pPath->InsertLineTo(DocCoord(117000,      0));
00288             if (ok) ok = pPath->CloseSubPath();
00289 
00290             if (!ok)
00291             {
00292                 delete pPath;
00293                 return FALSE;
00294             }
00295 
00296             pPath->IsFilled  = TRUE;
00297             pPath->IsStroked = FALSE;
00298 
00299             ArrowShape  = pPath;
00300             Centre      = DocCoord(0,0);
00301             LineWidth   = Width;
00302             ArrowWidth  = INT32(Size);
00303             ArrowHeight = INT32(Size);
00304             IsNull      = FALSE;
00305 
00306             StartArrow = FALSE;
00307 
00308             break;
00309 
00310         case SA_ANGLEDARROW:
00311 
00312             /*
00313             ANGLED
00314             -26.999 53.999 m
00315             -9 0 l
00316             -26.999 -54.001 l
00317             135 0 l
00318             -26.999 53.999 l
00319             */
00320 
00321             pPath = new Path();
00322             if (pPath == NULL)
00323                 return FALSE;
00324 
00325             ok = pPath->Initialise(5);
00326             if (ok)      pPath->FindStartOfPath();
00327             if (ok) ok = pPath->InsertMoveTo(DocCoord(-27000,  54000));
00328             if (ok) ok = pPath->InsertLineTo(DocCoord( -9000,      0));
00329             if (ok) ok = pPath->InsertLineTo(DocCoord(-27000, -54000));
00330             if (ok) ok = pPath->InsertLineTo(DocCoord(135000,      0));
00331             if (ok) ok = pPath->CloseSubPath();
00332 
00333             if (!ok)
00334             {
00335                 delete pPath;
00336                 return FALSE;
00337             }
00338 
00339             pPath->IsFilled  = TRUE;
00340             pPath->IsStroked = FALSE;
00341 
00342             ArrowShape  = pPath;
00343             Centre      = DocCoord(0,0);
00344             LineWidth   = Width;
00345             ArrowWidth  = INT32(Size);
00346             ArrowHeight = INT32(Size);
00347             IsNull      = FALSE;
00348 
00349             StartArrow = FALSE;
00350 
00351             break;
00352 
00353 
00354         case SA_ROUNDEDARROW:
00355 
00356             /*
00357             ROUND
00358             -9 0 m
00359             -9 -45 l
00360             -9 -51.708 2.808 -56.580 9 -54 c
00361             117 -9 l
00362             120.916 -7.369 126 -4.242 126 0 c
00363             126 4.242 120.916 7.369 117 9 c
00364             9 54 l
00365             2.808 56.580 -9 51.708 -9 45 c
00366             -9 0 l
00367             */
00368 
00369             pPath = new Path();
00370             if (pPath == NULL)
00371                 return FALSE;
00372 
00373             ok = pPath->Initialise(17);
00374             if (ok)      pPath->FindStartOfPath();
00375             if (ok) ok = pPath->InsertMoveTo( DocCoord(  -9000,      0));
00376             if (ok) ok = pPath->InsertLineTo( DocCoord(  -9000, -45000));
00377             if (ok) ok = pPath->InsertCurveTo(DocCoord(  -9000, -51708),
00378                                               DocCoord(   2808, -56580),
00379                                               DocCoord(   9000, -54000));
00380             if (ok) ok = pPath->InsertLineTo( DocCoord( 117000,  -9000));
00381             if (ok) ok = pPath->InsertCurveTo(DocCoord( 120916,  -7369),
00382                                               DocCoord( 126000,  -4242),
00383                                               DocCoord( 126000,      0));
00384             if (ok) ok = pPath->InsertCurveTo(DocCoord( 126000,   4242),
00385                                               DocCoord( 120916,   7369),
00386                                               DocCoord( 117000,   9000));
00387             if (ok) ok = pPath->InsertLineTo( DocCoord(   9000,  54000));
00388             if (ok) ok = pPath->InsertCurveTo(DocCoord(   2808,  56580),
00389                                               DocCoord(  -9000,  51708),
00390                                               DocCoord(  -9000,  45000));
00391             if (ok) ok = pPath->CloseSubPath();
00392 
00393             if (!ok)
00394             {
00395                 delete pPath;
00396                 return FALSE;
00397             }
00398 
00399             pPath->IsFilled  = TRUE;
00400             pPath->IsStroked = FALSE;
00401 
00402             ArrowShape  = pPath;
00403             Centre      = DocCoord(0,0);
00404             LineWidth   = Width;
00405             ArrowWidth  = INT32(Size);
00406             ArrowHeight = INT32(Size);
00407             IsNull      = FALSE;
00408 
00409             StartArrow = FALSE;
00410 
00411             break;
00412     
00413 
00414         case SA_SPOT:
00415 
00416             /*
00417             BLOB
00418             -54 0 m
00419             -54 29.807 -29.807 54 0 54 c
00420             29.807 54 54 29.807 54 0 c
00421             54 -29.807 29.807 -54 0 -54 c
00422             -29.807 -54 -54 -29.807 -54 0 c
00423             */
00424 
00425             pPath = new Path();
00426             if (pPath == NULL)
00427                 return FALSE;
00428 
00429             ok = pPath->Initialise(14);
00430             if (ok)      pPath->FindStartOfPath();
00431             if (ok) ok = pPath->InsertMoveTo( DocCoord( -54000,      0));
00432             if (ok) ok = pPath->InsertCurveTo(DocCoord( -54000,  29807),
00433                                               DocCoord( -29807,  54000),
00434                                               DocCoord(      0,  54000));
00435             if (ok) ok = pPath->InsertCurveTo(DocCoord(  29807,  54000),
00436                                               DocCoord(  54000,  29807),
00437                                               DocCoord(  54000,      0));
00438             if (ok) ok = pPath->InsertCurveTo(DocCoord(  54000, -29807),
00439                                               DocCoord(  29807, -54000),
00440                                               DocCoord(      0, -54000));
00441             if (ok) ok = pPath->InsertCurveTo(DocCoord( -29807, -54000),
00442                                               DocCoord( -54000, -29807),
00443                                               DocCoord( -54000,      0));
00444             if (ok) ok = pPath->CloseSubPath();
00445 
00446             if (!ok)
00447             {
00448                 delete pPath;
00449                 return FALSE;
00450             }
00451 
00452             pPath->IsFilled  = TRUE;
00453             pPath->IsStroked = FALSE;
00454 
00455             ArrowShape  = pPath;
00456             Centre      = DocCoord(0,0);
00457             LineWidth   = Width;
00458             ArrowWidth  = INT32(Size);
00459             ArrowHeight = INT32(Size);
00460             IsNull      = FALSE;
00461 
00462             StartArrow = TRUE;
00463 
00464             break;
00465     
00466 
00467         case SA_DIAMOND:
00468 
00469             /*
00470             DIAMOND
00471             -63 0 m
00472             0 63 l
00473             63 0 l
00474             0 -63 l
00475             -63 0 l
00476             */
00477 
00478             pPath = new Path();
00479             if (pPath == NULL)
00480                 return FALSE;
00481 
00482             ok = pPath->Initialise(5);
00483             if (ok)      pPath->FindStartOfPath();
00484             if (ok) ok = pPath->InsertMoveTo(DocCoord(-63000,      0));
00485             if (ok) ok = pPath->InsertLineTo(DocCoord(     0,  63000));
00486             if (ok) ok = pPath->InsertLineTo(DocCoord( 63000,      0));
00487             if (ok) ok = pPath->InsertLineTo(DocCoord(     0, -63000));
00488             if (ok) ok = pPath->CloseSubPath();
00489 
00490             if (!ok)
00491             {
00492                 delete pPath;
00493                 return FALSE;
00494             }
00495 
00496             pPath->IsFilled  = TRUE;
00497             pPath->IsStroked = FALSE;
00498 
00499             ArrowShape  = pPath;
00500             Centre      = DocCoord(0,0);
00501             LineWidth   = Width;
00502             ArrowWidth  = INT32(Size);
00503             ArrowHeight = INT32(Size);
00504             IsNull      = FALSE;
00505 
00506             StartArrow = TRUE;
00507 
00508             break;
00509     
00510         case SA_ARROWFEATHER:
00511 
00512             /*
00513             FEATHER
00514             18 -54 m
00515             108 -54 l
00516             63 0 l
00517             108 54 l
00518             18 54 l
00519             -36 0 l
00520             18 -54 l
00521             */
00522 
00523             pPath = new Path();
00524             if (pPath == NULL)
00525                 return FALSE;
00526 
00527             ok = pPath->Initialise(7);
00528             if (ok)      pPath->FindStartOfPath();
00529             if (ok) ok = pPath->InsertMoveTo(DocCoord( 18000, -54000));
00530             if (ok) ok = pPath->InsertLineTo(DocCoord(108000, -54000));
00531             if (ok) ok = pPath->InsertLineTo(DocCoord( 63000,      0));
00532             if (ok) ok = pPath->InsertLineTo(DocCoord(108000,  54000));
00533             if (ok) ok = pPath->InsertLineTo(DocCoord( 18000,  54000));
00534             if (ok) ok = pPath->InsertLineTo(DocCoord(-36000,      0));
00535             if (ok) ok = pPath->CloseSubPath();
00536 
00537             if (!ok)
00538             {
00539                 delete pPath;
00540                 return FALSE;
00541             }
00542 
00543             pPath->IsFilled  = TRUE;
00544             pPath->IsStroked = FALSE;
00545 
00546             ArrowShape  = pPath;
00547             Centre      = DocCoord(0,0);
00548             LineWidth   = Width;
00549             ArrowWidth  = INT32(Size);
00550             ArrowHeight = INT32(Size);
00551             IsNull      = FALSE;
00552 
00553             StartArrow = TRUE;
00554 
00555             break;
00556     
00557         case SA_ARROWFEATHER2:
00558 
00559             /*
00560             FEATHER3
00561             -35.998 0 m
00562             18 -54 l
00563             54 -54 l
00564             18 -18 l
00565             27 -18 l
00566             63 -54 l
00567             99 -54 l
00568             63 -18 l
00569             72 -18 l
00570             108 -54 l
00571             144 -54 l
00572             90 0 l
00573             144 54 l
00574             108 54 l
00575             72 18 l
00576             63 18 l
00577             99 54 l
00578             63 54 l
00579             27 18 l
00580             18 18 l
00581             54 54 l
00582             18 54 l
00583             -35.998 0 l
00584             */
00585 
00586             pPath = new Path();
00587             if (pPath == NULL)
00588                 return FALSE;
00589 
00590             ok = pPath->Initialise(23);
00591             if (ok)      pPath->FindStartOfPath();
00592             if (ok) ok = pPath->InsertMoveTo(DocCoord( -36000,      0));
00593             if (ok) ok = pPath->InsertLineTo(DocCoord(  18000, -54000));
00594             if (ok) ok = pPath->InsertLineTo(DocCoord(  54000, -54000));
00595             if (ok) ok = pPath->InsertLineTo(DocCoord(  18000, -18000));
00596             if (ok) ok = pPath->InsertLineTo(DocCoord(  27000, -18000));
00597             if (ok) ok = pPath->InsertLineTo(DocCoord(  63000, -54000));
00598             if (ok) ok = pPath->InsertLineTo(DocCoord(  99000, -54000));
00599             if (ok) ok = pPath->InsertLineTo(DocCoord(  63000, -18000));
00600             if (ok) ok = pPath->InsertLineTo(DocCoord(  72000, -18000));
00601             if (ok) ok = pPath->InsertLineTo(DocCoord( 108000, -54000));
00602             if (ok) ok = pPath->InsertLineTo(DocCoord( 144000, -54000));
00603             if (ok) ok = pPath->InsertLineTo(DocCoord(  90000,      0));
00604             if (ok) ok = pPath->InsertLineTo(DocCoord( 144000,  54000));
00605             if (ok) ok = pPath->InsertLineTo(DocCoord( 108000,  54000));
00606             if (ok) ok = pPath->InsertLineTo(DocCoord(  72000,  18000));
00607             if (ok) ok = pPath->InsertLineTo(DocCoord(  63000,  18000));
00608             if (ok) ok = pPath->InsertLineTo(DocCoord(  99000,  54000));
00609             if (ok) ok = pPath->InsertLineTo(DocCoord(  63000,  54000));
00610             if (ok) ok = pPath->InsertLineTo(DocCoord(  27000,  18000));
00611             if (ok) ok = pPath->InsertLineTo(DocCoord(  18000,  18000));
00612             if (ok) ok = pPath->InsertLineTo(DocCoord(  54000,  54000));
00613             if (ok) ok = pPath->InsertLineTo(DocCoord(  18000,  54000));
00614             if (ok) ok = pPath->CloseSubPath();
00615 
00616             if (!ok)
00617             {
00618                 delete pPath;
00619                 return FALSE;
00620             }
00621 
00622             pPath->IsFilled  = TRUE;
00623             pPath->IsStroked = FALSE;
00624 
00625             ArrowShape  = pPath;
00626             Centre      = DocCoord(0,0);
00627             LineWidth   = Width;
00628             ArrowWidth  = INT32(Size);
00629             ArrowHeight = INT32(Size);
00630             IsNull      = FALSE;
00631 
00632             StartArrow = TRUE;
00633 
00634             break;
00635     
00636         case SA_HOLLOWDIAMOND:
00637 
00638             /*
00639             HOLLOW
00640             0 45 m
00641             -45 0 l
00642             0 -45 l
00643             45 0 l
00644             0 45 l
00645             0 63 m
00646             -63 0 l
00647             0 -63 l
00648             63 0 l
00649             0 63 l
00650             */
00651 
00652             pPath = new Path();
00653             if (pPath == NULL)
00654                 return FALSE;
00655 
00656             ok = pPath->Initialise(10);
00657             if (ok)      pPath->FindStartOfPath();
00658             if (ok) ok = pPath->InsertMoveTo(DocCoord(     0,  45000));
00659             if (ok) ok = pPath->InsertLineTo(DocCoord(-45000,      0));
00660             if (ok) ok = pPath->InsertLineTo(DocCoord(     0, -45000));
00661             if (ok) ok = pPath->InsertLineTo(DocCoord( 45000,      0));
00662             if (ok) ok = pPath->CloseSubPath();
00663             if (ok) ok = pPath->InsertMoveTo(DocCoord(     0,  63000));
00664             if (ok) ok = pPath->InsertLineTo(DocCoord(-63000,      0));
00665             if (ok) ok = pPath->InsertLineTo(DocCoord(     0, -63000));
00666             if (ok) ok = pPath->InsertLineTo(DocCoord( 63000,      0));
00667             if (ok) ok = pPath->CloseSubPath();
00668 
00669             if (!ok)
00670             {
00671                 delete pPath;
00672                 return FALSE;
00673             }
00674 
00675             pPath->IsFilled  = TRUE;
00676             pPath->IsStroked = FALSE;
00677 
00678             ArrowShape  = pPath;
00679             Centre      = DocCoord(-45000,0);
00680             LineWidth   = Width;
00681             ArrowWidth  = INT32(Size);
00682             ArrowHeight = INT32(Size);
00683             IsNull      = FALSE;
00684 
00685             StartArrow = TRUE;
00686 
00687             break;
00688 
00689         default:
00690             ArrowShape  = NULL;
00691             Centre      = DocCoord(0,0);
00692 
00693             LineWidth   = DEFAULT_ARROW_LINEWIDTH;
00694             ArrowWidth  = 3;
00695             ArrowHeight = 3;
00696 
00697             StartArrow          = FALSE;
00698             ScaleWithLineWidth  = TRUE;
00699             ArrowID             = SA_NULLARROW;
00700             IsNull              = TRUE;
00701             break;
00702     }
00703 
00704     return TRUE;
00705 }
00706 
00707 /********************************************************************************************
00708 
00709 >   static String_256 ArrowRec::GetStockArrowName(StockArrow ArrowType)
00710 
00711     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00712     Created:    4/4/95
00713     Returns:    -
00714     Purpose:    Get a description of a Stock ArrowHead.
00715     Errors:     -
00716     SeeAlso:    -
00717 
00718 ********************************************************************************************/
00719 
00720 String_256 ArrowRec::GetStockArrowName(StockArrow ArrowType)
00721 {
00722     String_256 ArrowName = String_256(_R(IDS_K_ARROWS_DEFAULTARROW));
00723 
00724     switch (ArrowType)
00725     {
00726         case SA_STRAIGHTARROW:
00727             ArrowName.Load(_R(IDS_K_ARROWS_STRAIGHTARROW));
00728             break;
00729 
00730         case SA_ANGLEDARROW:
00731             ArrowName.Load(_R(IDS_K_ARROWS_ANGLEDARROW));
00732             break;
00733 
00734         case SA_ROUNDEDARROW:
00735             ArrowName.Load(_R(IDS_K_ARROWS_ROUNDEDARROW));
00736             break;
00737 
00738         case SA_SPOT:
00739             ArrowName.Load(_R(IDS_K_ARROWS_SPOT));
00740             break;
00741 
00742         case SA_DIAMOND:
00743             ArrowName.Load(_R(IDS_K_ARROWS_DIAMOND));
00744             break;
00745 
00746         case SA_ARROWFEATHER:
00747             ArrowName.Load(_R(IDS_K_ARROWS_ARROWFEATHER));
00748             break;
00749 
00750         case SA_ARROWFEATHER2:
00751             ArrowName.Load(_R(IDS_K_ARROWS_ARROWFEATHER2));
00752             break;
00753 
00754         case SA_HOLLOWDIAMOND:
00755             ArrowName.Load(_R(IDS_K_ARROWS_HOLLOWDIAMOND));
00756             break;
00757 
00758         default:
00759             ArrowName = "";
00760             break;
00761     }
00762 
00763     return ArrowName;
00764 }
00765 
00766 /********************************************************************************************
00767 
00768 >   void ArrowRec::SetArrowSize(FIXED16 Width, FIXED16 Height = 0)
00769 
00770     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00771     Created:    4/4/95
00772     Returns:    -
00773     Purpose:    Set the size of the ArrowHead
00774     Errors:     -
00775     SeeAlso:    -
00776 
00777 ********************************************************************************************/
00778 
00779 void ArrowRec::SetArrowSize(FIXED16 Width, FIXED16 Height)
00780 {
00781     ArrowWidth = Width;
00782     ArrowHeight = (Height > 0) ? Height : Width;
00783 }
00784 
00785 /********************************************************************************************
00786 
00787 >   ArrowRec& ArrowRec::operator=(const ArrowRec& OtherArrow)
00788 
00789     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00790     Created:    4/4/95
00791     Returns:    -
00792     Purpose:    Make one Arrow the same as another.
00793     Errors:     -
00794     SeeAlso:    -
00795 
00796 ********************************************************************************************/
00797 
00798 ArrowRec& ArrowRec::operator=(const ArrowRec& OtherArrow)
00799 {
00800     if (ArrowShape != NULL)
00801     {
00802         delete ArrowShape;      // Get rid of existing arrow path
00803         ArrowShape = NULL;
00804     }
00805 
00806     if (OtherArrow.ArrowShape != NULL)
00807     {
00808         // Now try and create a new one
00809         ArrowShape = new Path();
00810         if (ArrowShape == NULL)
00811             return (*this);
00812 
00813         // Copy the path data from the Other Arrow into our new path.
00814         BOOL    ok = ArrowShape->Initialise(OtherArrow.ArrowShape->GetNumCoords());
00815         if (ok) ok = ArrowShape->CopyPathDataFrom(OtherArrow.ArrowShape);
00816 
00817         if (!ok)
00818         {
00819             // Tidy up if we failed
00820             delete ArrowShape;
00821             ArrowShape = NULL;
00822         }
00823     }
00824 
00825     Centre      = OtherArrow.Centre;
00826 
00827     LineWidth   = OtherArrow.LineWidth;
00828     ArrowWidth  = OtherArrow.ArrowWidth;
00829     ArrowHeight = OtherArrow.ArrowHeight;
00830 
00831     StartArrow  = OtherArrow.StartArrow;
00832     ArrowID     = OtherArrow.ArrowID;
00833 
00834     ScaleWithLineWidth = OtherArrow.ScaleWithLineWidth;
00835 
00836     m_bExtendPath = OtherArrow.m_bExtendPath;
00837 
00838     IsNull      = OtherArrow.IsNull;
00839 
00840     return (*this);
00841 }
00842 
00843 /********************************************************************************************
00844 
00845 >   ArrowRec& ArrowRec::operator=(StockArrow ArrowType)
00846 
00847     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00848     Created:    4/4/95
00849     Inputs:     -
00850     Outputs:    -
00851     Returns:    -
00852     Purpose:    Make an arrow into a stock arrow.
00853     Errors:     -
00854     SeeAlso:    -
00855 
00856 ********************************************************************************************/
00857 
00858 ArrowRec& ArrowRec::operator=(StockArrow ArrowType)
00859 {
00860     // Now try and create a new one
00861     CreateStockArrow(ArrowType);
00862 
00863     return (*this);
00864 }
00865 
00866 /********************************************************************************************
00867 
00868 >   INT32 ArrowRec::operator==(const ArrowRec& OtherArrow)
00869 
00870     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00871     Created:    4/4/95
00872     Inputs:     -
00873     Returns:    -
00874     Purpose:    Test to see if this ArrowHead is the same as another.
00875     Errors:     -
00876     SeeAlso:    -
00877 
00878 ********************************************************************************************/
00879 
00880 INT32 ArrowRec::operator==(const ArrowRec& OtherArrow)
00881 {
00882     if (ArrowShape == NULL && OtherArrow.ArrowShape == NULL)
00883         return TRUE;
00884 
00885     if (ArrowShape == NULL || OtherArrow.ArrowShape == NULL)
00886         return FALSE;
00887 
00888     INT32 NumCoords         = ArrowShape->GetNumCoords();
00889     INT32 OtherNumCoords = OtherArrow.ArrowShape->GetNumCoords();
00890 
00891     if (NumCoords != OtherNumCoords)
00892         return FALSE;
00893 
00894     DocCoord* Coords    = ArrowShape->GetCoordArray(); 
00895     PathVerb* Verbs     = ArrowShape->GetVerbArray(); 
00896 
00897     DocCoord* OtherCoords   = OtherArrow.ArrowShape->GetCoordArray(); 
00898     PathVerb* OtherVerbs    = OtherArrow.ArrowShape->GetVerbArray(); 
00899 
00900     for (INT32 i=0; i<NumCoords; i++)
00901     {
00902         if (Coords[i] != OtherCoords[i] || Verbs[i] != OtherVerbs[i])
00903             return FALSE;
00904     }
00905 
00906     TRACEUSER( "DavidM", wxT("ArrowRec::operator == %d %d\n"),
00907         m_bExtendPath, OtherArrow.m_bExtendPath);
00908 
00909     return (Centre      == OtherArrow.Centre        &&
00910             LineWidth   == OtherArrow.LineWidth     &&
00911             ArrowWidth  == OtherArrow.ArrowWidth    &&
00912             ArrowHeight == OtherArrow.ArrowHeight   &&
00913             StartArrow  == OtherArrow.StartArrow    &&
00914             m_bExtendPath == OtherArrow.m_bExtendPath);
00915 }
00916 
00917 /********************************************************************************************
00918 
00919 >   INT32 ArrowRec::operator==(StockArrow ArrowType)
00920 
00921     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00922     Created:    4/4/95
00923     Inputs:     -
00924     Returns:    -
00925     Purpose:    Test to see if this ArrowHead is the same as another.
00926     Errors:     -
00927     SeeAlso:    -
00928 
00929 ********************************************************************************************/
00930 
00931 INT32 ArrowRec::operator==(StockArrow ArrowType)
00932 {
00933     ArrowRec TempArrow;
00934     TempArrow.CreateStockArrow(ArrowType);
00935     TempArrow.m_bExtendPath = m_bExtendPath;
00936 
00937     return (*this == TempArrow);
00938 }
00939 
00940 /********************************************************************************************
00941 
00942 >   Path* ArrowRec::GetArrowPath()
00943 
00944     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00945     Created:    4/4/95
00946     Returns:    -
00947     Purpose:    Get the path describing the shape of this ArrowHead.
00948     SeeAlso:    -
00949 
00950 ********************************************************************************************/
00951 
00952 Path* ArrowRec::GetArrowPath()
00953 {
00954     return ArrowShape;
00955 }
00956 
00957 /********************************************************************************************
00958 
00959 >   DocCoord ArrowRec::GetArrowCentre()
00960 
00961     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00962     Created:    4/4/95
00963     Returns:    -
00964     Purpose:    Get the centre of the Arrow (relative to the Arrow Path coordinates).
00965     SeeAlso:    -
00966 
00967 ********************************************************************************************/
00968 
00969 DocCoord ArrowRec::GetArrowCentre()
00970 {
00971     return Centre;
00972 }
00973 
00974 /********************************************************************************************
00975 
00976 >   INT32 ArrowRec::GetArrowLineWidth()
00977 
00978     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00979     Created:    4/4/95
00980     Returns:    -
00981     Purpose:    Get the line width that this arrow was defined for.
00982     SeeAlso:    -
00983 
00984 ********************************************************************************************/
00985 
00986 INT32 ArrowRec::GetArrowLineWidth()
00987 {
00988     return LineWidth;
00989 }
00990 
00991 /********************************************************************************************
00992 
00993 >   FIXED16 ArrowRec::GetArrowWidth()
00994 
00995     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00996     Created:    4/4/95
00997     Returns:    -
00998     Purpose:    Get the width scaling of this arrow head.
00999                 (How much it is stretched horizontally).
01000     SeeAlso:    -
01001 
01002 ********************************************************************************************/
01003 
01004 FIXED16 ArrowRec::GetArrowWidth()
01005 {
01006     return ArrowWidth;
01007 }
01008 
01009 /********************************************************************************************
01010 
01011 >   FIXED16 ArrowRec::GetArrowHeight()
01012 
01013     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01014     Created:    4/4/95
01015     Returns:    -
01016     Purpose:    Get the Height scaling of this arrow head.
01017                 (How much it is stretched Vertically).
01018     SeeAlso:    -
01019 
01020 ********************************************************************************************/
01021 
01022 FIXED16 ArrowRec::GetArrowHeight()
01023 {
01024     return ArrowHeight;
01025 }
01026 
01027 /********************************************************************************************
01028 
01029 >   BOOL ArrowRec::IsStartArrow()
01030 
01031     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01032     Created:    12/4/95
01033     Returns:    -
01034     Purpose:    Is this arrow designed to be a Start or End arrow.
01035     SeeAlso:    -
01036 
01037 ********************************************************************************************/
01038 
01039 BOOL ArrowRec::IsStartArrow()
01040 {
01041     return StartArrow;
01042 }
01043 
01044 BOOL ArrowRec::ShouldScaleWithLineWidth()
01045 {
01046     return ScaleWithLineWidth;
01047 }
01048 
01049 INT32 ArrowRec::GetArrowID()
01050 {
01051     return ArrowID;
01052 }
01053 
01054 /********************************************************************************************
01055 
01056 >   DocRect ArrowRec::GetArrowBoundingRect(Path* pParent, INT32 ParentLineWidth, BOOL StartArrow)
01057 
01058     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01059     Created:    4/4/95
01060     Inputs:     pParent, The Path to get the Arrow Bounds of.
01061                 ParentLineWidth, The current applied LineWidth of the Path.
01062                 StartArrow, TRUE = Calc StartArrow Bounds, FALSE = Calc EndArrow Bounds.
01063 
01064     Returns:    The Union of all the bounds of ArrowHeads on this Path.
01065     Purpose:    Calculates the Union of all the bounds of ArrowHeads on a Path.
01066                 The path may have many subpaths, so it will union the Bounds of the Arrows
01067                 on the Start or End of each subpath.
01068     Errors:     -
01069     SeeAlso:    -
01070 
01071 ********************************************************************************************/
01072 
01073 DocRect ArrowRec::GetArrowBoundingRect(Path* pParent, INT32 ParentLineWidth, BOOL StartArrow)
01074 {
01075     if (IsNullArrow())
01076         return DocRect(0,0,0,0);    // Hopefully we won't be asked for our bounds
01077                                     // if we are NULL.  But just in case ...
01078 
01079     // We will now try and find the total bounds of the ArrowHeads,
01080     // on this path.  The path may be made up of many subpaths, so
01081     // we'll need to union the bounds of each ArrowHead on the end
01082     // of each subpath.
01083 
01084     DocRect Bounds(0,0,0,0);
01085 
01086     INT32 PathIndex = 0;
01087     DocCoord ArrowCentre;
01088     DocCoord ArrowDirection;
01089 
01090     DocCoord* Coords = pParent->GetCoordArray(); 
01091     PathVerb* Verbs = pParent->GetVerbArray(); 
01092     INT32 NumCoords = pParent->GetNumCoords();
01093 
01094 
01095     // Find the first position of an ArrowHead
01096     BOOL GotPos = GetFirstArrowPos(StartArrow,
01097                                    Coords, Verbs, NumCoords, 
01098                                    &PathIndex, &ArrowCentre, &ArrowDirection);
01099     while (GotPos)
01100     {
01101         // Union all the Bounds of the Arrows on each subpath
01102         Bounds = Bounds.Union(FindBoundsAt(ArrowCentre, ArrowDirection, ParentLineWidth));
01103 
01104         // Find the next Arrow position (if there are any more subpaths)
01105         GotPos = GetNextArrowPos(StartArrow,
01106                                  Coords, Verbs, NumCoords, 
01107                                  &PathIndex, &ArrowCentre, &ArrowDirection);
01108     }
01109     
01110     // Return the Union of all the arrow bounds
01111     return Bounds;
01112 }
01113 
01114 /********************************************************************************************
01115 
01116 >   DocRect ArrowRec::FindBoundsAt(const DocCoord& Centre, const DocCoord& Direction,
01117                                    INT32 ParentLineWidth)
01118 
01119     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01120     Created:    4/4/95
01121     Inputs:     Centre, The Centre point (in Spread Coords) of the Arrow.
01122                 Direction, A Spread coord specifying the arrow direction (Relative to Centre).
01123                 ParentLineWidth, The LineWidth of the Path.
01124 
01125     Returns:    The Bounds of the arrow at this position.
01126     Purpose:    Finds the Bounds of this ArrowHead at the Specified position.
01127     Errors:     -
01128     SeeAlso:    -
01129 
01130 ********************************************************************************************/
01131 
01132 DocRect ArrowRec::FindBoundsAt(const DocCoord& ArrowCentre, const DocCoord& Direction, 
01133                                INT32 ParentLineWidth)
01134 {
01135     DocRect Bounds(0,0,0,0);
01136 
01137     // Find a matrix to transform the ArrowHead to this Position.
01138     Trans2DMatrix Trans;
01139     GetArrowMatrix(ArrowCentre, Direction, ParentLineWidth, &Trans);
01140 
01141     // Note:
01142     // We should really be able to ask Gavin to Calculate the Bounds,
01143     // and pass him this Transform Matrix, but he can't do this at the
01144     // moment, so we'll have to actually transform the path into
01145     // a tempory path, and then ask him to calc the bounds of that.
01146 
01147     // Make a tempory path to transform
01148     Path* TransPath = new Path();
01149     if (TransPath == NULL)
01150         return Bounds;
01151 
01152     // Copy the path data from the ArrorHead into our tempory path.
01153     BOOL    ok = TransPath->Initialise(ArrowShape->GetNumCoords());
01154     if (ok) ok = TransPath->CopyPathDataFrom(ArrowShape);
01155 
01156     if (!ok)
01157     {
01158         // Tidy up if we failed
01159         delete TransPath;
01160         return Bounds;
01161     }
01162 
01163     // Go transform the Tempory path
01164     Trans.Transform(TransPath->GetCoordArray(), 
01165                     TransPath->GetNumCoords() );
01166 
01167     BOOL GDrawResult = FALSE;
01168     
01169     // Find out what the paths bounding rect is, taking into account
01170     // any bezier curve thingies. 
01171 
01172     GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
01173     
01174     if (GD != NULL)
01175         GDrawResult = GD->CalcStrokeBBox((POINT*)TransPath->GetCoordArray(),
01176                                             TransPath->GetVerbArray(), TransPath->GetNumCoords(),
01177                                             (RECT *)(&Bounds),
01178                                             TRUE, 0, CAPS_ROUND, JOIN_ROUND, NULL) == 0;
01179 
01180     // If Gavin failed, then use backup technique of getting coord array bounds
01181     if (!GDrawResult)
01182         Bounds = TransPath->GetBoundingRect();
01183 
01184     // Delete the temporary transformed path
01185     delete TransPath;
01186 
01187     return Bounds;
01188 }
01189 
01190 /********************************************************************************************
01191 
01192 >   BOOL ArrowRec::GetArrowMatrix(const DocCoord& Centre, const DocCoord& Direction, 
01193                                   INT32 ParentLineWidth, Trans2DMatrix* pMatrix)
01194 
01195     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01196     Created:    4/4/95
01197     Inputs:     -
01198     Outputs:    -
01199     Returns:    -
01200     Purpose:    Gets a Transform Matrix for this ArrowHead, given the specified position.
01201     Errors:     -
01202     SeeAlso:    -
01203 
01204 ********************************************************************************************/
01205 
01206 BOOL ArrowRec::GetArrowMatrix(const DocCoord& ArrowCentre, const DocCoord& Direction, 
01207                               INT32 ParentLineWidth, Trans2DMatrix* pMatrix)
01208 {
01209     if (IsNullArrow())
01210         return FALSE;
01211 
01212     TRACEUSER( "DavidM", wxT("ArrowRec::GetArrowMatrix %d\n"), m_bExtendPath );
01213 
01214     ANGLE RotateAngle = CalcAngle(ArrowCentre, Direction);
01215 
01216     // Now we work how much we need to scale the path
01217     DocRect ArrowBounds = ArrowShape->GetBoundingRect();
01218 
01219     double TempLineWidth = ParentLineWidth;
01220 
01221     if (TempLineWidth == 0)
01222         TempLineWidth = ZEROWIDTH_ARROW_LINEWIDTH;
01223 
01224     BOOL DoScale = ScaleWithLineWidth;
01225 
01226     FIXED16 xscale = DoScale ? ((ArrowWidth.MakeDouble() * TempLineWidth) / LineWidth)
01227                              :  (ArrowWidth);
01228     FIXED16 yscale = DoScale ? ((ArrowHeight.MakeDouble() * TempLineWidth) / LineWidth)
01229                              :  (ArrowWidth);
01230 
01231     // move the centre of the arrow
01232     DocRect ArrowRect = ArrowShape->GetBoundingRect();
01233     
01234     DocCoord centre;
01235         
01236     if (!m_bExtendPath)
01237     {
01238         centre.x = ArrowRect.hi.x;
01239         centre.y = (ArrowRect.lo.y + ArrowRect.hi.y) / 2;
01240     }
01241     else
01242     {
01243         centre = Centre;
01244     }
01245     
01246     Matrix Mat = Matrix(-centre.x,
01247                         -centre.y);                 // Move shape to origin
01248     Mat *= Matrix(xscale, yscale);                  // Scale it
01249     Mat *= Matrix(RotateAngle);                     // Rotate it
01250 
01251     Mat *= Matrix(ArrowCentre);                     // Move it to the line point
01252 
01253     Trans2DMatrix Trans(Mat);
01254 
01255     *pMatrix = Trans;
01256 
01257     return TRUE;
01258 }
01259 
01260 /********************************************************************************************
01261 
01262 >   static BOOL ArrowRec::DoesPathNeedArrowHeads(Path* pPath)
01263 
01264     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01265     Created:    4/4/95
01266     Inputs:     -
01267     Outputs:    -
01268     Returns:    -
01269     Purpose:    Determines whether a path has any open subpaths which will need arrows
01270                 drawn onto.
01271     Errors:     -
01272     SeeAlso:    -
01273 
01274 ********************************************************************************************/
01275 
01276 BOOL ArrowRec::DoesPathNeedArrowHeads(DocCoord* Coords, PathVerb* Verbs, INT32 NumCoords)
01277 {
01278     // Scan for subpaths, and check to see if they're closed or not.
01279     BOOL FoundCloseFigure = TRUE;
01280 
01281     for (INT32 coord=0; coord<NumCoords; coord++)
01282     {
01283         if (Verbs[coord] == PT_MOVETO)
01284         {
01285             if (!FoundCloseFigure)
01286                 return TRUE;    // Got a MOVETO before a CLOSEFIGURE, 
01287                                 // so must be at least one open subpath
01288 
01289             FoundCloseFigure = FALSE;
01290         }
01291 
01292         if (Verbs[coord] & PT_CLOSEFIGURE)
01293         {
01294             FoundCloseFigure = TRUE;
01295         }
01296     }
01297 
01298     if (!FoundCloseFigure)
01299         return TRUE;
01300 
01301     return FALSE;
01302 }
01303 
01304 /********************************************************************************************
01305 
01306 >   static BOOL ArrowRec::GetFirstArrowPos(Path* pPath, BOOL StartArrow, 
01307                                            INT32* Index, DocCoord* Centre, DocCoord* Direction)
01308 
01309     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01310     Created:    4/4/95
01311     Inputs:     -
01312     Outputs:    -
01313     Returns:    -
01314     Purpose:    Scans a path for the first position on a ArrowHead.
01315     Errors:     -
01316     SeeAlso:    -
01317 
01318 ********************************************************************************************/
01319 
01320 BOOL ArrowRec::GetFirstArrowPos(BOOL StartArrow,
01321                                 DocCoord* Coords, PathVerb* Verbs, INT32 NumCoords,
01322                                 INT32* Index, DocCoord* Centre, DocCoord* Direction)
01323 {
01324     *Index = 0;     // Start at the beginning of the path
01325 
01326     // And scan for open subpaths
01327     return GetNextArrowPos(StartArrow, Coords, Verbs, NumCoords, Index, Centre, Direction);
01328 }
01329 
01330 /********************************************************************************************
01331 
01332 >   static BOOL ArrowRec::GetNextArrowPos(Path* pPath, BOOL StartArrow, 
01333                                           INT32* Index, DocCoord* Centre, DocCoord* Direction)
01334 
01335     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01336     Created:    4/4/95
01337     Inputs:     -
01338     Outputs:    -
01339     Returns:    -
01340     Purpose:    Scans a path for the next position on a ArrowHead.
01341     Errors:     -
01342     SeeAlso:    -
01343 
01344 ********************************************************************************************/
01345 
01346 BOOL ArrowRec::GetNextArrowPos(BOOL StartArrow, 
01347                                DocCoord* Coords, PathVerb* Verbs, INT32 NumCoords,
01348                                INT32* Index, DocCoord* Centre, DocCoord* Direction)
01349 {
01350     INT32 coord = *Index;
01351     INT32 StartPos = -1;        // Look for next subpath start
01352 
01353     while (coord<NumCoords)
01354     {
01355         if (Verbs[coord] == PT_MOVETO)
01356         {
01357             if (StartPos != -1)
01358                 break;          // Break out, We've found an open subpath !!
01359 
01360             StartPos = coord;   // Remember the Subpath start pos
01361         }
01362 
01363         if (Verbs[coord] & PT_CLOSEFIGURE)
01364         {
01365             StartPos = -1;      // Look for next subpath
01366         }
01367     
01368         coord++;
01369     }
01370 
01371     if (StartPos != -1)
01372     {
01373         // We've found an open subpath !!
01374         if (StartArrow)
01375         {
01376             *Centre     = Coords[StartPos];
01377             *Direction  = Coords[StartPos+1];
01378 
01379             // move the centre back by the direction & the size of the arrow
01380             
01381         }
01382         else
01383         {
01384             *Centre     = Coords[coord-1];
01385             *Direction  = Coords[coord-2];
01386         }
01387 
01388         *Index = coord;
01389         
01390         return TRUE;
01391     }
01392 
01393     // There are no more open subpaths
01394     return FALSE;
01395 }
01396 
01397 /********************************************************************************************
01398 
01399 >   static ANGLE ArrowRec::CalcAngle(const DocCoord& Centre, const DocCoord& Direction)
01400 
01401     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01402     Created:    4/4/95
01403     Inputs:     -
01404     Outputs:    -
01405     Returns:    -
01406     Purpose:    Calculates the angle of a Line, given the Centre point,
01407                 and a point specifying the direction. 0 is due East.
01408     Errors:     -
01409     SeeAlso:    -
01410 
01411 ********************************************************************************************/
01412 
01413 ANGLE ArrowRec::CalcAngle(const DocCoord& ArrowCentre, const DocCoord& Direction)
01414 {
01415     ANGLE Angle;
01416 
01417     // Calculate the angle of the arrow from the line angle
01418     const INT32 dx = Direction.x - ArrowCentre.x;
01419     const INT32 dy = Direction.y - ArrowCentre.y;
01420 
01421     if ( (dy==0) && (dx==0) )
01422     {
01423         return FALSE;           // Too small
01424     }
01425 
01426     double LineAngle;
01427 
01428     if ( (dx>=0) && (dy>=0) )
01429         LineAngle = -PI + atan2( (double)dy, (double)dx );
01430     else if ( (dx<0) && (dy>=0) )
01431         LineAngle = -atan2( (double)dy, (double)-dx );
01432     else if ( (dx<0) && (dy<0) )
01433         LineAngle = atan2( (double)-dy, (double)-dx );
01434     else if ( (dx>=0) && (dy<0) )
01435         LineAngle = PI - atan2( (double)-dy, (double)dx );
01436 
01437     else
01438     {
01439         TRACE( wxT("invalid angle in CalcAngle\n") );       // this should be impossible
01440         return FALSE;
01441     }
01442 
01443     Angle = 360 * (LineAngle / (2*PI)); // Convert from radians to degrees
01444 
01445     return Angle;
01446 }
01447 
01448 /********************************************************************************************
01449 
01450 >   void ArrowRec::GetBasePoint(DocCoord * pPoint)
01451 
01452     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01453     Created:    25/2/99
01454     Inputs:     The doccoord to put the point into
01455     Outputs:    -
01456     Returns:    -
01457     Purpose:    Gives the base point for this particular arrow (stock arrow)
01458                 Note : HEAVILY dependent on the stock arrow paths
01459     Errors:     -
01460     SeeAlso:    -
01461 
01462 ********************************************************************************************/
01463 
01464 void ArrowRec::GetArrowBase(DocCoord * pPoint)
01465 {
01466     if (!pPoint)
01467         return;
01468 
01469     DocRect ArrowRect = ArrowShape->GetBoundingRect();
01470 
01471     switch (ArrowID)
01472     {
01473     case SA_STRAIGHTARROW:
01474         pPoint->x = -9000;
01475         pPoint->y = 0;
01476         break;
01477     case SA_ANGLEDARROW:
01478         pPoint->x = -9000;
01479         pPoint->y = 0;
01480         break;
01481     case SA_ROUNDEDARROW:
01482         pPoint->x = -9000;
01483         pPoint->y = 0;
01484         break;
01485     case SA_SPOT:
01486         pPoint->x = -30000;
01487         pPoint->y = (ArrowRect.hi.y + ArrowRect.lo.y) / 2;
01488         break;
01489     case SA_DIAMOND:
01490         pPoint->x = -54000;
01491         pPoint->y = (ArrowRect.hi.y + ArrowRect.lo.y) / 2;
01492         break;
01493     case SA_ARROWFEATHER:
01494         pPoint->x = -30000;
01495         pPoint->y = (ArrowRect.hi.y + ArrowRect.lo.y) / 2;
01496         break;
01497     case SA_ARROWFEATHER2:
01498         pPoint->x = -30000;
01499         pPoint->y = (ArrowRect.hi.y + ArrowRect.lo.y) / 2;
01500         break;
01501     case SA_HOLLOWDIAMOND:
01502         pPoint->x = -54000;
01503         pPoint->y = (ArrowRect.hi.y + ArrowRect.lo.y) / 2;
01504         break;
01505     default:
01506         pPoint->x = ArrowRect.lo.x;
01507         pPoint->y = (ArrowRect.hi.y + ArrowRect.lo.y) / 2;
01508         break;
01509     }
01510 }
01511 

Generated on Sat Nov 10 03:44:11 2007 for Camelot by  doxygen 1.4.4