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 }