ppbevel.cpp

Go to the documentation of this file.
00001 // $Id: ppbevel.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 // ppbevel - Definition of bevel BevelPathProcessor class
00099 
00100 #include "camtypes.h"
00101 
00102 #include "ppbevel.h"
00103 
00104 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 #include "pathtrap.h"
00107 #include "bevtrap.h"
00108 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "gclips.h"
00112 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "attrbev.h"
00114 
00115 CC_IMPLEMENT_DYNAMIC(BevelPathProcessor, PathProcessor);
00116 CC_IMPLEMENT_DYNAMIC(BevelAttributePathProcessor, PathProcessor);
00117 
00118 // Declare smart memory handling in Debug builds
00119 #define new CAM_DEBUG_NEW
00120 
00122 // Clipping & flattening consts
00123 const MILLIPOINT BevelPathProcessor_Flatness = 200;
00124 const MILLIPOINT BevelPathProcessor_Tolerance = 50;
00125 
00126 #define SHRINKSCALE 0.5
00127 
00128 /********************************************************************************************
00129 
00130 >   BevelPathProcessor::BevelPathProcessor()
00131 
00132 
00133     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
00134     Created:    12/11/98
00135 
00136     Purpose:    Constructor
00137 
00138 ********************************************************************************************/
00139 
00140 INT32 num = 0;
00141 
00142 BevelPathProcessor::BevelPathProcessor(BOOL bShrinkPath)
00143 {
00144     m_bShrinkPath = bShrinkPath;
00145     m_bIsPathClosed = TRUE;
00146 }
00147 
00148 /********************************************************************************************
00149 
00150 >   virtual BevelPathProcessor::~BevelPathProcessor()
00151 
00152     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
00153     Created:    12/11/98
00154 
00155     Purpose:    Destructor
00156     
00157     Errors:     If this object still has a non-NULL Next pointer, it will ERROR3 in
00158                 an effort to get you to clean up properly before destruction.
00159 
00160 ********************************************************************************************/
00161 
00162 BevelPathProcessor::~BevelPathProcessor()
00163 {
00164 }
00165 
00166 /********************************************************************************************
00167 
00168 >   void BevelPathProcessor::ProcessPath(Path *pPath,
00169                                          RenderRegion *pRender,
00170                                          PathShape ShapePath = PATHSHAPE_PATH)
00171 
00172     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
00173     Created:    12/11/98
00174 
00175     Purpose:    Adds the given path to the path in me for a bevel node to use
00176 
00177 ********************************************************************************************/
00178 void BevelPathProcessor::ProcessPath(Path *pPath,
00179                                      RenderRegion *pRender,
00180                                      PathShape ShapePath)
00181 {
00182     PORTNOTETRACE("other","BevelPathProcessor::PreOpProcessing - do nothing");
00183 #ifndef EXCLUDE_FROM_XARALX
00184     pRender->SaveContext();
00185 
00186     BOOL bPathIsClosed = pPath->IsClosed();
00187 
00188     if (m_bIsPathClosed && !bPathIsClosed)
00189     {
00190         m_bIsPathClosed = FALSE;
00191     }
00192 
00193     Path ShrunkPath;
00194     ShrunkPath.Initialise();
00195 
00196     // get the line width from the render region
00197     StrokeColourAttribute * pStrokeColour = (StrokeColourAttribute *)pRender->GetCurrentAttribute(ATTR_STROKECOLOUR);
00198 
00199     BOOL bShrinkPath = m_bShrinkPath;
00200     
00201     if (pStrokeColour)
00202     {
00203         if (pStrokeColour->GetStartColour())
00204         {
00205             if (!(pStrokeColour->GetStartColour()->IsTransparent()))
00206             {
00207                 bShrinkPath = FALSE;
00208             }
00209         }
00210     }
00211 
00212     if (bShrinkPath && bPathIsClosed)
00213     {
00214         // flatten the path first
00215         ProcessFlatten Flatten(200);
00216 
00217         Path FlatPath;
00218         FlatPath.Initialise();
00219 
00220         ProcessFlags pf(TRUE, FALSE, FALSE);
00221         Flatten.FlattenPath(pf, pPath, &FlatPath);
00222 
00223         // ensure that the path is correct
00224         Path ClippedPath;
00225         ClippedPath.Initialise();
00226 
00227         Path CopyPath;
00228         CopyPath.Initialise();
00229         CopyPath.CloneFrom(FlatPath);
00230 
00231         FlatPath.ClipPathToPath(CopyPath, &ClippedPath, 3, 50, 200, 200);
00232 
00233         BevelHelpers::ShrinkPath(&ClippedPath, pRender->GetScaledPixelWidth(),
00234             pRender->GetScaledPixelWidth(), &ShrunkPath);
00235 
00236         pRender->DrawPath(&ShrunkPath, this, ShapePath);
00237     }
00238     else
00239     {
00240         pRender->DrawPath(pPath, this, ShapePath);
00241     }
00242 
00243     pRender->RestoreContext();
00244 #endif
00245 }
00246 
00247 /********************************************************************************************
00248 
00249 >   static void BevelPathProcessor::ShrinkPath(Path * pSrcPath, 
00250                                     double amountX,
00251                                     double amountY, 
00252                                     Path * pRetnPath)
00253 
00254 
00255     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00256     Created:    29/10/98
00257     Purpose:    Shrinks the path very slightly so that antialiasing doesn't bleed out
00258                 of the bevel
00259     SeeAlso:    -
00260 
00261 ********************************************************************************************/
00262 void BevelHelpers::ShrinkPath(Path * pSrcPath, double amountX, double amountY, 
00263                                     Path * pRetnPath, BOOL bTest)
00264 {
00265     if (!pSrcPath || !pRetnPath)
00266         return;
00267 
00268     if (pSrcPath->GetNumCoords() < 3)
00269     {
00270         pRetnPath->CloneFrom(*pSrcPath);
00271         return;
00272     }
00273     
00274     if (amountX == 0 || amountY == 0)
00275         return;
00276 
00277     pRetnPath->ClearPath();
00278     pRetnPath->CloneFrom(*pSrcPath);
00279 
00280     DocCoord dcBefore;
00281     DocCoord dcThis;
00282     DocCoord dcAfter;
00283     DocCoord dcTest;
00284 
00285     DocRect testRect;
00286     DocRect thisRect;
00287 
00288     NormCoord ncBefore;
00289     NormCoord ncAfter;
00290     NormCoord ncAverage;
00291 
00292     double dt = 0;
00293 //  double dot = 0;
00294 
00295     INT32 IStart = 0;
00296     INT32 IEnd = 0;
00297 
00298     double BeforeLen = 0;
00299     double AfterLen  = 0;
00300     double LenAverage = 0;
00301 
00302     BOOL bOK = FALSE;
00303 
00304     // first, calculate the normal list
00305     NormCoord *pNormList = new NormCoord[pSrcPath->GetNumCoords()];
00306     
00307     for (INT32 i = 0 ; i < pSrcPath->GetNumCoords(); i++)
00308     {
00309         // get the points before & after
00310         IStart = i - 1;
00311         IEnd = i + 1;
00312         
00313         if (i == pSrcPath->GetNumCoords() - 1)
00314         {
00315             IEnd = i;
00316             pSrcPath->FindStartOfSubPath(&IEnd);
00317             IEnd ++;
00318         }
00319         else if (pSrcPath->GetVerbArray()[i] == PT_MOVETO)
00320         {
00321             // find the end of the sub-path
00322             IStart = i;
00323             pSrcPath->FindEndElOfSubPath(&IStart);
00324             IStart -= 1;
00325         }
00326         else if (pSrcPath->GetVerbArray()[i+1] == PT_MOVETO)
00327         {
00328             IEnd = i;
00329             pSrcPath->FindStartOfSubPath(&IEnd);
00330             IEnd ++;
00331         }
00332         
00333         dcBefore = pSrcPath->GetCoordArray()[IStart];
00334         dcThis = pSrcPath->GetCoordArray()[i];
00335         dcAfter = pSrcPath->GetCoordArray()[IEnd];
00336 
00337         ncBefore.x = dcThis.x - dcBefore.x;
00338         ncBefore.y = dcThis.y - dcBefore.y;
00339         BeforeLen = 1/ncBefore.GetLength();
00340 
00341         if (BeforeLen > 0)
00342         {
00343             ncBefore.x *= BeforeLen;
00344             ncBefore.y *= BeforeLen;
00345         }
00346 
00347         ncAfter.x = dcAfter.x - dcThis.x;
00348         ncAfter.y = dcAfter.y - dcThis.y;
00349         AfterLen = 1/ncAfter.GetLength();
00350 
00351         if (AfterLen > 0)
00352         {
00353             ncAfter.x *= AfterLen;
00354             ncAfter.y *= AfterLen;
00355         }
00356         
00357         ncAverage.x = ncBefore.x + ncAfter.x;
00358         ncAverage.y = ncBefore.y + ncAfter.y;
00359         
00360         LenAverage = 1/ncAverage.GetLength();
00361 
00362         // do the normal
00363         if (LenAverage > 0)
00364         {
00365             ncAverage.x *= LenAverage;
00366             ncAverage.y *= LenAverage;
00367         
00368             // rotate by 90 degrees
00369             dt = ncAverage.x;
00370             ncAverage.x = -ncAverage.y;
00371             ncAverage.y = dt;
00372 
00373             pNormList[i] = ncAverage;
00374         }
00375     }                      
00376 
00377     INT32 AbsAmountX = abs((INT32)(amountX));
00378     INT32 AbsAmountY = abs((INT32)(amountY));
00379     INT32 NextIndex = 0;
00380 
00381     DocCoord intersection;
00382     double p = 0;
00383     double q = 0;
00384     
00385     BOOL bDoTest = FALSE;
00386 
00387     // now, run through the list again calculating bounding rects
00388     for (INT32 i = 0 ; i < pSrcPath->GetNumCoords(); i++)
00389     {
00390         dcThis = pSrcPath->GetCoordArray()[i];
00391         
00392         // only do this on single sub-paths (quicker !)
00393         /*
00394         if (pSrcPath->GetVerbArray()[i] == PT_MOVETO)
00395         {
00396             IStart = i;
00397             IEnd = i;
00398             pSrcPath->FindEndElOfSubPath(&IEnd);
00399         }
00400         */
00401 
00402         IStart = 0;
00403         IEnd = pSrcPath->GetNumCoords();
00404         
00405         // is sub path in list ?
00406         bOK = TRUE;
00407 
00408         IStart = 0;
00409         IEnd = pSrcPath->GetNumCoords();
00410 
00411         thisRect.lo.x = dcThis.x - AbsAmountX;
00412         thisRect.lo.y = dcThis.y - AbsAmountY;
00413         thisRect.hi.x = dcThis.x + AbsAmountX;
00414         thisRect.hi.y = dcThis.y + AbsAmountY;
00415         
00416         for (INT32 j = IStart; j <= IEnd && bOK; j++)
00417         {
00418             // get the line segment to test         
00419             dcTest = pSrcPath->GetCoordArray()[j];
00420             
00421             bDoTest = TRUE;
00422 
00423             if (i == IStart)
00424             {
00425                 if (j == IEnd || j == i || j == i+1)
00426                 {
00427                     bDoTest = FALSE;
00428                 }
00429             }
00430             else if (i == IEnd)
00431             {
00432                 if (j == IEnd - 1 || j == i || j == IStart)
00433                 {
00434                     bDoTest = FALSE;
00435                 }
00436             }
00437             else if (j == i - 1 || j == i || j == i+1)
00438             {
00439                 bDoTest = FALSE;
00440             }
00441             
00442             if (bDoTest)
00443             {
00444                 NextIndex = j + 1;
00445                 
00446                 if (NextIndex == IEnd)
00447                 {
00448                     NextIndex = IStart;
00449                 }
00450                 
00451                 dcAfter = pSrcPath->GetCoordArray()[NextIndex];
00452                 
00453                 // do the bounding rect
00454                 if (dcTest.x < dcAfter.x)
00455                 {
00456                     testRect.lo.x = dcTest.x;
00457                     testRect.hi.x = dcAfter.x;
00458                 }
00459                 else
00460                 {
00461                     testRect.lo.x = dcAfter.x;
00462                     testRect.hi.x = dcTest.x;
00463                 }
00464                 
00465                 if (dcTest.y < dcAfter.y)
00466                 {
00467                     testRect.lo.y = dcTest.y;
00468                     testRect.hi.y = dcAfter.y;
00469                 }
00470                 else
00471                 {
00472                     testRect.lo.y = dcAfter.y;
00473                     testRect.hi.y = dcTest.y;
00474                 }
00475                 
00476                 if (testRect.IsIntersectedWith(thisRect))
00477                 {
00478                     // check if when we move the point the point changes sides from
00479                     // one side of the line segment to the other
00480                     ncAverage.x = dcTest.x - dcAfter.x;
00481                     ncAverage.y = dcTest.y - dcAfter.y;
00482                     
00483                     if (CCreateBevelTrapezoids::CalculateIntersection(&dcThis, &(pNormList[i]),
00484                         &dcAfter, &ncAverage, 
00485                         &intersection, &p, &q))
00486                     {
00487                         if (intersection.x > testRect.lo.x && intersection.x < testRect.hi.x &&
00488                             intersection.y > testRect.lo.y && intersection.y < testRect.hi.y)
00489                         {
00490                             // get the length of the line
00491                             ncAverage.x = dcThis.x - intersection.x;
00492                             ncAverage.y = dcThis.y - intersection.y;
00493 
00494                             q = ncAverage.GetLength();
00495 
00496                             if (q > 0)
00497                             {
00498                                 if (q < fabs(amountX*2))
00499                                 {
00500                                     bOK = FALSE;
00501                                 }
00502                             }
00503 
00504                         }
00505                     }
00506                 }           
00507             }
00508         }
00509 
00510         if (bOK)
00511         {
00512             dcThis.x = (INT32)((((double)dcThis.x) - (pNormList[i].x * amountX)));
00513             dcThis.y = (INT32)((((double)dcThis.y) - (pNormList[i].y * amountY)));
00514                     
00515             pRetnPath->GetCoordArray()[i] = dcThis;
00516         }       
00517     }
00518 
00519     delete [] pNormList;
00520     pNormList = NULL;
00521 
00522     /*
00523     Path StrokedPath;
00524     StrokedPath.Initialise();
00525 
00526     pSrcPath->StrokePathToPath((INT32)(amountX*2),
00527                               LineCapButt,
00528                               MitreJoin,
00529                               NULL,
00530                               &StrokedPath,
00531                               BEVEL_FLATNESS/5,
00532                               TRUE);
00533     
00534     // need to flatten this
00535     ProcessFlatten Flatten(BEVEL_FLATNESS/5);
00536 
00537     Path FlatPath;
00538     FlatPath.Initialise();
00539 
00540     pRetnPath->ClearPath(FALSE);
00541     pRetnPath->Initialise();
00542     
00543     ProcessFlags pf(TRUE, FALSE, FALSE);
00544     Flatten.FlattenPath(pf, &StrokedPath, &FlatPath);
00545 
00546     if (!bAdd)
00547     {
00548         FlatPath.ClipPathToPath(pSrcPath, 
00549             pRetnPath,
00550             1 | CLIPPING_SOURCE_WINDING,
00551             0, BEVEL_FLATNESS/5, BEVEL_FLATNESS/5);
00552     }
00553     else
00554     {
00555         FlatPath.ClipPathToPath(pSrcPath, 
00556             pRetnPath,
00557             7 | CLIPPING_SOURCE_WINDING,
00558             0, BEVEL_FLATNESS/5, BEVEL_FLATNESS/5);
00559     }
00560     */
00561 
00562 
00563     pRetnPath->IsFilled = TRUE;
00564     pRetnPath->IsStroked = FALSE;
00565 
00566 }
00567 
00568 /********************************************************************************************
00569 
00570 >   static BOOL BevelHelpers::IsPathToBeReversed(Path * pPath)
00571 
00572     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00573     Created:    29/10/98
00574     Purpose:    Indicates that the path is around the wrong way for bevelling i.e.
00575                 the normals will be facing outwards, not inwards
00576     Notes:      The path must have no sub-paths
00577     SeeAlso:    -
00578 
00579 ********************************************************************************************/
00580 
00581 BOOL BevelHelpers::IsPathToBeReversed(Path * pPath)
00582 {
00583     NormCoord ncBefore;
00584     NormCoord ncAfter;
00585     NormCoord ncBefore90;
00586 
00587     double TotalDot = 0;
00588     double dot1 = 0;
00589     double dot2 = 0;
00590 
00591     DocRect Bounds = pPath->GetBoundingRect();
00592     DocCoord Centre ;
00593     Centre.x = Bounds.lo.x + (Bounds.Width() / 2);
00594     Centre.y = Bounds.lo.y + (Bounds.Height() / 2);
00595 
00596     UINT32 Count = 0;
00597     
00598     for (INT32 i = 0; i < pPath->GetNumCoords()-1; i++)
00599     {
00600         if (i > 0 && pPath->GetVerbArray()[i] == PT_MOVETO)
00601             break;
00602 
00603         Count ++;
00604         
00605         // get the points before & after
00606         ncBefore.x = pPath->GetCoordArray()[i].x - Centre.x;
00607         ncBefore.y = pPath->GetCoordArray()[i].y - Centre.y;
00608         
00609         ncAfter.x = pPath->GetCoordArray()[i+1].x - Centre.x;
00610         ncAfter.y = pPath->GetCoordArray()[i+1].y - Centre.y;
00611 
00612         ncBefore.Normalise();
00613         ncAfter.Normalise();
00614 
00615         ncBefore90.y = -ncBefore.x;
00616         ncBefore90.x =  ncBefore.y;
00617 
00618         dot1 = ncBefore90.x * ncAfter.x + ncBefore90.y * ncAfter.y;
00619         dot2 = ncBefore.x * ncAfter.x + ncBefore.y * ncAfter.y;
00620 
00621         TotalDot += dot1;
00622     }
00623 
00624     TotalDot /= (double)Count;
00625 
00626     TRACEUSER( "DavidM", _T("Total %f\n"), TotalDot);
00627 
00628     return (TotalDot < -0.05);
00629 }
00630 
00631 /********************************************************************************************
00632 
00633 >   void BevelHelpers::EliminateMultiplePoints(Path * pPath)
00634 
00635     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00636     Created:    20/1/99
00637     Purpose:    Eliminates multiple points in the path
00638                 Path must be flat !
00639     SeeAlso:    -
00640 
00641 ********************************************************************************************/
00642 void BevelHelpers::EliminateMultiplePoints(Path * pPath)
00643 {   
00644     Path NewPath;
00645     NewPath.Initialise();
00646 
00647     // flatten the path
00648     pPath->Flatten(200, &NewPath);
00649     pPath->CloneFrom(NewPath);
00650     pPath->IsFilled = TRUE;
00651     pPath->IsStroked = FALSE;
00652 
00653     NewPath.ClearPath();
00654     NewPath.IsFilled = TRUE;
00655     NewPath.IsStroked = FALSE;
00656 
00657     DocCoord dc1(0,0);
00658     DocCoord dc2;
00659 
00660     INT32 StartIndex = 0;
00661 
00662     for (INT32 i = 0 ; i < pPath->GetNumCoords(); i++)
00663     {
00664         dc2 = pPath->GetCoordArray()[i];
00665 
00666         // ensure that dc1 is different to dc2 on first index
00667         if (i == 0)
00668         {
00669             dc1.x = dc2.x - 1000;
00670         }
00671         
00672         if (dc2.x != dc1.x ||
00673             dc2.y != dc1.y ||
00674             pPath->GetVerbArray()[i] == PT_MOVETO)
00675         {
00676             if (pPath->GetVerbArray()[i] == PT_MOVETO)
00677             {
00678                 /*
00679                 if (i > 0)
00680                 {
00681                     // make sure we close the path
00682                     if (NewPath.GetCoordArray()[i - 1].x != NewPath.GetCoordArray()[StartIndex].x ||
00683                         NewPath.GetCoordArray()[i - 1].y != NewPath.GetCoordArray()[StartIndex].y)
00684                     {
00685                         NewPath.AddLineTo(NewPath.GetCoordArray()[StartIndex]);
00686                     }
00687                 }
00688                 */
00689 
00690                 NewPath.AddMoveTo(dc2);
00691                 StartIndex = i;
00692             }
00693             else
00694             {
00695                 NewPath.AddLineTo(dc2);
00696             }
00697         }
00698 
00699         dc1 = dc2;
00700     }
00701 
00702     // make sure we close the path
00703     /*
00704     if (NewPath.GetCoordArray()[i - 1].x != NewPath.GetCoordArray()[StartIndex].x ||
00705         NewPath.GetCoordArray()[i - 1].y != NewPath.GetCoordArray()[StartIndex].y)
00706     {
00707         NewPath.AddLineTo(NewPath.GetCoordArray()[StartIndex]);
00708     }
00709     */
00710 
00711     pPath->ClearPath();
00712     pPath->CloneFrom(NewPath);
00713 }
00714 
00715 
00716 
00718 // BevelAttributePathProcessor implementation
00719 /********************************************************************************************
00720 
00721 >   BevelAttributePathProcessor::BevelAttributePathProcessor()
00722 
00723     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
00724     Created:    12/11/98
00725 
00726     Purpose:    Constructor
00727 
00728 ********************************************************************************************/
00729 BevelAttributePathProcessor::BevelAttributePathProcessor()
00730 {
00731     m_SummedPath.Initialise();
00732     m_StrokedPath.Initialise();
00733     m_Indent = 0;
00734 }
00735 
00736 
00737 /********************************************************************************************
00738 
00739 >   BevelAttributePathProcessor::~BevelAttributePathProcessor()
00740 
00741     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
00742     Created:    12/11/98
00743 
00744     Purpose:    Destructor
00745 
00746 ********************************************************************************************/
00747 BevelAttributePathProcessor::~BevelAttributePathProcessor()
00748 {
00749 
00750 }
00751 
00752 
00753 /********************************************************************************************
00754 
00755 >   void BevelAttributePathProcessor::ProcessPath(Path *pPath,
00756                                                   RenderRegion *pRender,
00757                                                   PathShape ShapePath = PATHSHAPE_PATH)
00758 
00759     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
00760     Created:    12/11/98
00761 
00762     Purpose:    Adds the given path to the path in me for a bevel node to use
00763 
00764 ********************************************************************************************/
00765 void BevelAttributePathProcessor::ProcessPath(Path *pPath,
00766                                               RenderRegion *pRender,
00767                                               PathShape ShapePath)
00768 {
00769 //  PORTNOTETRACE("other","BevelAttributePathProcessor::PreOpProcessing - do nothing");
00770 //#ifndef EXCLUDE_FROM_XARALX
00771     // pRender->DrawPath(pPath, this);
00772 
00773     // clip the path to itself
00774     Path BlankPath;
00775     BlankPath.Initialise();
00776 
00777     Path SafePath;
00778     SafePath.Initialise();
00779 
00780     pPath->ClipPathToPath(BlankPath, &SafePath, 6, BevelPathProcessor_Tolerance, 
00781         BevelPathProcessor_Flatness,
00782         BevelPathProcessor_Flatness);
00783 
00784     // now, sum the path
00785     m_SummedPath.MergeTwoPaths(SafePath);
00786 
00787     Path StrokedPath;
00788     StrokedPath.Initialise();
00789 
00790     SafePath.StrokePathToPath(abs(m_Indent)*2,
00791                             LineCapButt,
00792                             RoundJoin,
00793                             NULL,
00794                             &StrokedPath,
00795                             BevelPathProcessor_Flatness,
00796                             FALSE);
00797 
00798     // now, clip this path against the original (i.e. the passed in) path to
00799     // produce the final clipped path
00800     Path ClippedPath;
00801     ClippedPath.Initialise();
00802 
00803     // shrink the clipped path
00804     Path ShrunkPath;
00805     ShrunkPath.Initialise();
00806 
00807     if (m_Indent < 0)
00808     {
00809         pPath->ClipPathToPath(StrokedPath, &ClippedPath, 7 | CLIPPING_SOURCE_WINDING,
00810             BevelPathProcessor_Tolerance, BevelPathProcessor_Flatness,
00811             BevelPathProcessor_Flatness);
00812 
00813         BevelHelpers::ShrinkPath(&ClippedPath, pRender->GetScaledPixelWidth(), pRender->GetScaledPixelWidth(),
00814                             &ShrunkPath, FALSE);
00815 
00816         ClippedPath.CloneFrom(ShrunkPath);
00817 
00818         // merge the original path (reversed) into this path to produce a hole for 
00819         // outer bevels
00820         Path ReversedPath;
00821         ReversedPath.Initialise();
00822         ReversedPath.CloneFrom(SafePath);
00823         ReversedPath.Reverse();
00824         ClippedPath.MergeTwoPaths(ReversedPath);
00825     }
00826     else
00827     {
00828         pPath->ClipPathToPath(StrokedPath, &ClippedPath, 2 | CLIPPING_SOURCE_WINDING,
00829             BevelPathProcessor_Tolerance, BevelPathProcessor_Flatness,
00830             BevelPathProcessor_Flatness);
00831 
00832         BevelHelpers::ShrinkPath(&ClippedPath, pRender->GetScaledPixelWidth(), pRender->GetScaledPixelWidth(),
00833                             &ShrunkPath, FALSE);
00834 
00835         ClippedPath.CloneFrom(ShrunkPath);      
00836     }
00837 
00838     // merge this path with the stroked path member variable - as the attribute needs
00839     // it too
00840     m_StrokedPath.MergeTwoPaths(ClippedPath);
00841 
00842     // render the path with the same parameters
00843     ClippedPath.IsFilled = TRUE;
00844     ClippedPath.IsStroked = FALSE;
00845 
00846     pRender->SaveContext();
00847     pRender->SetLineColour(COLOUR_NONE);
00848 
00849     pRender->DrawPath(&ClippedPath, this, ShapePath);
00850     pRender->RestoreContext();
00851 //#endif
00852 }

Generated on Sat Nov 10 03:46:32 2007 for Camelot by  doxygen 1.4.4