Bounds returns the exact bounding box rectangle of the path.
()
| 1106 | |
| 1107 | // Bounds returns the exact bounding box rectangle of the path. |
| 1108 | func (p *Path) Bounds() Rect { |
| 1109 | if len(p.d) < 4 { |
| 1110 | return Rect{} |
| 1111 | } |
| 1112 | |
| 1113 | // first command is MoveTo |
| 1114 | start, end := Point{p.d[1], p.d[2]}, Point{} |
| 1115 | xmin, xmax := start.X, start.X |
| 1116 | ymin, ymax := start.Y, start.Y |
| 1117 | for i := 4; i < len(p.d); { |
| 1118 | cmd := p.d[i] |
| 1119 | switch cmd { |
| 1120 | case MoveToCmd, LineToCmd, CloseCmd: |
| 1121 | end = Point{p.d[i+1], p.d[i+2]} |
| 1122 | xmin = math.Min(xmin, end.X) |
| 1123 | xmax = math.Max(xmax, end.X) |
| 1124 | ymin = math.Min(ymin, end.Y) |
| 1125 | ymax = math.Max(ymax, end.Y) |
| 1126 | case QuadToCmd: |
| 1127 | cp := Point{p.d[i+1], p.d[i+2]} |
| 1128 | end = Point{p.d[i+3], p.d[i+4]} |
| 1129 | |
| 1130 | xmin = math.Min(xmin, end.X) |
| 1131 | xmax = math.Max(xmax, end.X) |
| 1132 | if tdenom := (start.X - 2*cp.X + end.X); !Equal(tdenom, 0.0) { |
| 1133 | if t := (start.X - cp.X) / tdenom; IntervalExclusive(t, 0.0, 1.0) { |
| 1134 | x := quadraticBezierPos(start, cp, end, t) |
| 1135 | xmin = math.Min(xmin, x.X) |
| 1136 | xmax = math.Max(xmax, x.X) |
| 1137 | } |
| 1138 | } |
| 1139 | |
| 1140 | ymin = math.Min(ymin, end.Y) |
| 1141 | ymax = math.Max(ymax, end.Y) |
| 1142 | if tdenom := (start.Y - 2*cp.Y + end.Y); !Equal(tdenom, 0.0) { |
| 1143 | if t := (start.Y - cp.Y) / tdenom; IntervalExclusive(t, 0.0, 1.0) { |
| 1144 | y := quadraticBezierPos(start, cp, end, t) |
| 1145 | ymin = math.Min(ymin, y.Y) |
| 1146 | ymax = math.Max(ymax, y.Y) |
| 1147 | } |
| 1148 | } |
| 1149 | case CubeToCmd: |
| 1150 | cp1 := Point{p.d[i+1], p.d[i+2]} |
| 1151 | cp2 := Point{p.d[i+3], p.d[i+4]} |
| 1152 | end = Point{p.d[i+5], p.d[i+6]} |
| 1153 | |
| 1154 | a := -start.X + 3*cp1.X - 3*cp2.X + end.X |
| 1155 | b := 2*start.X - 4*cp1.X + 2*cp2.X |
| 1156 | c := -start.X + cp1.X |
| 1157 | t1, t2 := solveQuadraticFormula(a, b, c) |
| 1158 | |
| 1159 | xmin = math.Min(xmin, end.X) |
| 1160 | xmax = math.Max(xmax, end.X) |
| 1161 | if !math.IsNaN(t1) && IntervalExclusive(t1, 0.0, 1.0) { |
| 1162 | x1 := cubicBezierPos(start, cp1, cp2, end, t1) |
| 1163 | xmin = math.Min(xmin, x1.X) |
| 1164 | xmax = math.Max(xmax, x1.X) |
| 1165 | } |