optimizeClose removes a superfluous first line segment in-place of a subpath. If both the first and last segment are line segments and are colinear, move the start of the path forward one segment
()
| 596 | |
| 597 | // optimizeClose removes a superfluous first line segment in-place of a subpath. If both the first and last segment are line segments and are colinear, move the start of the path forward one segment |
| 598 | func (p *Path) optimizeClose() { |
| 599 | if len(p.d) == 0 || p.d[len(p.d)-1] != CloseCmd { |
| 600 | return |
| 601 | } |
| 602 | |
| 603 | // find last MoveTo |
| 604 | end := Point{} |
| 605 | iMoveTo := len(p.d) |
| 606 | for 0 < iMoveTo { |
| 607 | cmd := p.d[iMoveTo-1] |
| 608 | iMoveTo -= cmdLen(cmd) |
| 609 | if cmd == MoveToCmd { |
| 610 | end = Point{p.d[iMoveTo+1], p.d[iMoveTo+2]} |
| 611 | break |
| 612 | } |
| 613 | } |
| 614 | |
| 615 | if p.d[iMoveTo] == MoveToCmd && p.d[iMoveTo+cmdLen(MoveToCmd)] == LineToCmd && iMoveTo+cmdLen(MoveToCmd)+cmdLen(LineToCmd) < len(p.d)-cmdLen(CloseCmd) { |
| 616 | // replace Close + MoveTo + LineTo by Close + MoveTo if equidirectional |
| 617 | // move Close and MoveTo forward along the path |
| 618 | start := Point{p.d[len(p.d)-cmdLen(CloseCmd)-3], p.d[len(p.d)-cmdLen(CloseCmd)-2]} |
| 619 | nextEnd := Point{p.d[iMoveTo+cmdLen(MoveToCmd)+cmdLen(LineToCmd)-3], p.d[iMoveTo+cmdLen(MoveToCmd)+cmdLen(LineToCmd)-2]} |
| 620 | if Equal(end.Sub(start).AngleBetween(nextEnd.Sub(end)), 0.0) { |
| 621 | // update Close |
| 622 | p.d[len(p.d)-3] = nextEnd.X |
| 623 | p.d[len(p.d)-2] = nextEnd.Y |
| 624 | |
| 625 | // update MoveTo |
| 626 | p.d[iMoveTo+1] = nextEnd.X |
| 627 | p.d[iMoveTo+2] = nextEnd.Y |
| 628 | |
| 629 | // remove LineTo |
| 630 | p.d = append(p.d[:iMoveTo+cmdLen(MoveToCmd)], p.d[iMoveTo+cmdLen(MoveToCmd)+cmdLen(LineToCmd):]...) |
| 631 | } |
| 632 | } |
| 633 | } |
| 634 | |
| 635 | //////////////////////////////////////////////////////////////// |
| 636 |
no test coverage detected