00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 #include "camtypes.h"
00101 
00102 #include "ppbevel.h"
00103 
00104 
00105 
00106 #include "pathtrap.h"
00107 #include "bevtrap.h"
00108 
00109 
00110 
00111 #include "gclips.h"
00112 
00113 #include "attrbev.h"
00114 
00115 CC_IMPLEMENT_DYNAMIC(BevelPathProcessor, PathProcessor);
00116 CC_IMPLEMENT_DYNAMIC(BevelAttributePathProcessor, PathProcessor);
00117 
00118 
00119 #define new CAM_DEBUG_NEW
00120 
00122 
00123 const MILLIPOINT BevelPathProcessor_Flatness = 200;
00124 const MILLIPOINT BevelPathProcessor_Tolerance = 50;
00125 
00126 #define SHRINKSCALE 0.5
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
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 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 BevelPathProcessor::~BevelPathProcessor()
00163 {
00164 }
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
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     
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         
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         
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 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
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 
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     
00305     NormCoord *pNormList = new NormCoord[pSrcPath->GetNumCoords()];
00306     
00307     for (INT32 i = 0 ; i < pSrcPath->GetNumCoords(); i++)
00308     {
00309         
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             
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         
00363         if (LenAverage > 0)
00364         {
00365             ncAverage.x *= LenAverage;
00366             ncAverage.y *= LenAverage;
00367         
00368             
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     
00388     for (INT32 i = 0 ; i < pSrcPath->GetNumCoords(); i++)
00389     {
00390         dcThis = pSrcPath->GetCoordArray()[i];
00391         
00392         
00393         
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402         IStart = 0;
00403         IEnd = pSrcPath->GetNumCoords();
00404         
00405         
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             
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                 
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                     
00479                     
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                             
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 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563     pRetnPath->IsFilled = TRUE;
00564     pRetnPath->IsStroked = FALSE;
00565 
00566 }
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
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         
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 
00634 
00635 
00636 
00637 
00638 
00639 
00640 
00641 
00642 void BevelHelpers::EliminateMultiplePoints(Path * pPath)
00643 {   
00644     Path NewPath;
00645     NewPath.Initialise();
00646 
00647     
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         
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 
00680 
00681 
00682 
00683 
00684 
00685 
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     
00703     
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711     pPath->ClearPath();
00712     pPath->CloneFrom(NewPath);
00713 }
00714 
00715 
00716 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 BevelAttributePathProcessor::BevelAttributePathProcessor()
00730 {
00731     m_SummedPath.Initialise();
00732     m_StrokedPath.Initialise();
00733     m_Indent = 0;
00734 }
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 BevelAttributePathProcessor::~BevelAttributePathProcessor()
00748 {
00749 
00750 }
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 void BevelAttributePathProcessor::ProcessPath(Path *pPath,
00766                                               RenderRegion *pRender,
00767                                               PathShape ShapePath)
00768 {
00769 
00770 
00771     
00772 
00773     
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     
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     
00799     
00800     Path ClippedPath;
00801     ClippedPath.Initialise();
00802 
00803     
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         
00819         
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     
00839     
00840     m_StrokedPath.MergeTwoPaths(ClippedPath);
00841 
00842     
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 
00852 }