#include <ppbevel.h>
Inheritance diagram for BevelHelpers:
Static Public Member Functions | |
static void | ShrinkPath (Path *pSrcPath, double amountX, double amountY, Path *pRetnPath, BOOL bTest=TRUE) |
Shrinks the path very slightly so that antialiasing doesn't bleed out of the bevel. | |
static BOOL | IsPathToBeReversed (Path *pPath) |
Indicates that the path is around the wrong way for bevelling i.e. the normals will be facing outwards, not inwards Notes: The path must have no sub-paths. | |
static void | EliminateMultiplePoints (Path *pPath) |
Eliminates multiple points in the path Path must be flat ! |
Definition at line 177 of file ppbevel.h.
|
Eliminates multiple points in the path Path must be flat !
Definition at line 642 of file ppbevel.cpp. 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 }
|
|
Indicates that the path is around the wrong way for bevelling i.e. the normals will be facing outwards, not inwards Notes: The path must have no sub-paths.
Definition at line 581 of file ppbevel.cpp. 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 }
|
|
Shrinks the path very slightly so that antialiasing doesn't bleed out of the bevel.
Definition at line 262 of file ppbevel.cpp. 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 }
|