mirror of
https://github.com/golang/go
synced 2024-11-24 23:27:57 -07:00
exp/draw: clip destination rectangle to the image bounds.
image: introduce Intersect and Union rectangle methods. R=r, rog, nigeltao CC=golang-dev https://golang.org/cl/2115043
This commit is contained in:
parent
6c8b85273c
commit
2deee2936c
@ -60,9 +60,10 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
|
||||
if r.Dy() > dy {
|
||||
r.Max.Y = r.Min.Y + dy
|
||||
}
|
||||
|
||||
// TODO(nigeltao): Clip r to dst's bounding box, and handle the case when sp or mp has negative X or Y.
|
||||
// TODO(nigeltao): Ensure that r is well formed, i.e. r.Max.X >= r.Min.X and likewise for Y.
|
||||
r = r.Intersect(dst.Bounds())
|
||||
if r.Empty() {
|
||||
return
|
||||
}
|
||||
|
||||
// Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation.
|
||||
if dst0, ok := dst.(*image.RGBA); ok {
|
||||
|
@ -37,6 +37,9 @@ func Pt(X, Y int) Point {
|
||||
}
|
||||
|
||||
// A Rectangle contains the points with Min.X <= X < Max.X, Min.Y <= Y < Max.Y.
|
||||
// It is well-formed if Min.X <= Max.X and likewise for Y. Points are always
|
||||
// well-formed. A rectangle's methods always return well-formed outputs for
|
||||
// well-formed inputs.
|
||||
type Rectangle struct {
|
||||
Min, Max Point
|
||||
}
|
||||
@ -72,12 +75,63 @@ func (r Rectangle) Sub(p Point) Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Inset returns the rectangle r inset by n, which may be negative.
|
||||
// Inset returns the rectangle r inset by n, which may be negative. If either
|
||||
// of r's dimensions is less than 2*n then an empty rectangle near the center
|
||||
// of r will be returned.
|
||||
func (r Rectangle) Inset(n int) Rectangle {
|
||||
return Rectangle{
|
||||
Point{r.Min.X + n, r.Min.Y + n},
|
||||
Point{r.Max.X - n, r.Max.Y - n},
|
||||
if r.Dx() < 2*n {
|
||||
r.Min.X = (r.Min.X + r.Max.X) / 2
|
||||
r.Max.X = r.Min.X
|
||||
} else {
|
||||
r.Min.X += n
|
||||
r.Max.X -= n
|
||||
}
|
||||
if r.Dy() < 2*n {
|
||||
r.Min.Y = (r.Min.Y + r.Max.Y) / 2
|
||||
r.Max.Y = r.Min.Y
|
||||
} else {
|
||||
r.Min.Y += n
|
||||
r.Max.Y -= n
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Intersect returns the largest rectangle contained by both r and s. If the
|
||||
// two rectangles do not overlap then the zero rectangle will be returned.
|
||||
func (r Rectangle) Intersect(s Rectangle) Rectangle {
|
||||
if r.Min.X < s.Min.X {
|
||||
r.Min.X = s.Min.X
|
||||
}
|
||||
if r.Min.Y < s.Min.Y {
|
||||
r.Min.Y = s.Min.Y
|
||||
}
|
||||
if r.Max.X > s.Max.X {
|
||||
r.Max.X = s.Max.X
|
||||
}
|
||||
if r.Max.Y > s.Max.Y {
|
||||
r.Max.Y = s.Max.Y
|
||||
}
|
||||
if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y {
|
||||
return ZR
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Union returns the smallest rectangle that contains both r and s.
|
||||
func (r Rectangle) Union(s Rectangle) Rectangle {
|
||||
if r.Min.X > s.Min.X {
|
||||
r.Min.X = s.Min.X
|
||||
}
|
||||
if r.Min.Y > s.Min.Y {
|
||||
r.Min.Y = s.Min.Y
|
||||
}
|
||||
if r.Max.X < s.Max.X {
|
||||
r.Max.X = s.Max.X
|
||||
}
|
||||
if r.Max.Y < s.Max.Y {
|
||||
r.Max.Y = s.Max.Y
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Empty returns whether the rectangle contains no points.
|
||||
@ -103,9 +157,8 @@ func (r Rectangle) Contains(p Point) bool {
|
||||
p.Y >= r.Min.Y && p.Y < r.Max.Y
|
||||
}
|
||||
|
||||
// Canon returns the canonical version of r. The returned rectangle has
|
||||
// minimum and maximum coordinates swapped if necessary so that Min.X <= Max.X
|
||||
// and Min.Y <= Max.Y.
|
||||
// Canon returns the canonical version of r. The returned rectangle has minimum
|
||||
// and maximum coordinates swapped if necessary so that it is well-formed.
|
||||
func (r Rectangle) Canon() Rectangle {
|
||||
if r.Max.X < r.Min.X {
|
||||
r.Min.X, r.Max.X = r.Max.X, r.Min.X
|
||||
|
Loading…
Reference in New Issue
Block a user