59 lines
1.5 KiB
Go
59 lines
1.5 KiB
Go
package artist
|
|
|
|
import "image"
|
|
import "image/color"
|
|
|
|
// Border represents a border that can be fed to MultiBorder.
|
|
type Border struct {
|
|
Weight int
|
|
Stroke Pattern
|
|
bounds image.Rectangle
|
|
dx, dy int
|
|
}
|
|
|
|
// MultiBorder is a pattern that allows multiple borders of different lengths to
|
|
// be inset within one another. The final border is treated as a fill color, and
|
|
// its weight does not matter.
|
|
type MultiBorder struct {
|
|
borders []Border
|
|
lastWidth, lastHeight int
|
|
maxBorder int
|
|
}
|
|
|
|
// NewMultiBorder creates a new MultiBorder pattern from the given list of
|
|
// borders.
|
|
func NewMultiBorder (borders ...Border) (multi *MultiBorder) {
|
|
return &MultiBorder { borders: borders }
|
|
}
|
|
|
|
// AtWhen satisfies the Pattern interface.
|
|
func (multi *MultiBorder) AtWhen (x, y, width, height int) (c color.RGBA) {
|
|
if multi.lastWidth != width || multi.lastHeight != height {
|
|
multi.recalculate(width, height)
|
|
}
|
|
point := image.Point { x, y }
|
|
for index := multi.maxBorder; index >= 0; index -- {
|
|
border := multi.borders[index]
|
|
if point.In(border.bounds) {
|
|
return border.Stroke.AtWhen (
|
|
point.X - border.bounds.Min.X,
|
|
point.Y - border.bounds.Min.Y,
|
|
border.dx, border.dy)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (multi *MultiBorder) recalculate (width, height int) {
|
|
bounds := image.Rect (0, 0, width, height)
|
|
multi.maxBorder = 0
|
|
for index, border := range multi.borders {
|
|
multi.maxBorder = index
|
|
multi.borders[index].bounds = bounds
|
|
multi.borders[index].dx = bounds.Dx()
|
|
multi.borders[index].dy = bounds.Dy()
|
|
bounds = bounds.Inset(border.Weight)
|
|
if bounds.Empty() { break }
|
|
}
|
|
}
|