This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
tomo-old/artist/shapes/rectangle.go

131 lines
3.3 KiB
Go
Raw Normal View History

2023-02-23 18:55:19 -07:00
package shapes
import "image"
import "image/color"
2023-02-23 18:55:19 -07:00
import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/shatter"
// TODO: return updatedRegion for all routines in this package
2023-02-23 18:55:19 -07:00
func FillRectangle (
destination canvas.Canvas,
source canvas.Canvas,
bounds image.Rectangle,
2023-02-23 18:55:19 -07:00
) (
updatedRegion image.Rectangle,
) {
dstData, dstStride := destination.Buffer()
srcData, srcStride := source.Buffer()
offset := source.Bounds().Min.Sub(destination.Bounds().Min)
drawBounds :=
source.Bounds().Sub(offset).
Intersect(destination.Bounds()).
Intersect(bounds)
if drawBounds.Empty() { return }
updatedRegion = drawBounds
2023-02-23 18:55:19 -07:00
2023-02-26 12:27:38 -07:00
point := image.Point { }
for point.Y = drawBounds.Min.Y; point.Y < drawBounds.Max.Y; point.Y ++ {
for point.X = drawBounds.Min.X; point.X < drawBounds.Max.X; point.X ++ {
2023-02-26 12:27:38 -07:00
offsetPoint := point.Add(offset)
dstIndex := point.X + point.Y * dstStride
srcIndex := offsetPoint.X + offsetPoint.Y * srcStride
dstData[dstIndex] = srcData[srcIndex]
2023-02-23 18:55:19 -07:00
}}
return
}
func StrokeRectangle (
destination canvas.Canvas,
source canvas.Canvas,
bounds image.Rectangle,
2023-02-23 18:55:19 -07:00
weight int,
) (
updatedRegion image.Rectangle,
2023-02-23 18:55:19 -07:00
) {
insetBounds := bounds.Inset(weight)
if insetBounds.Empty() {
return FillRectangle(destination, source, bounds)
2023-02-23 18:55:19 -07:00
}
return FillRectangleShatter(destination, source, insetBounds)
2023-02-23 18:55:19 -07:00
}
// FillRectangleShatter is like FillRectangle, but it does not draw in areas
// specified in "rocks".
func FillRectangleShatter (
destination canvas.Canvas,
source canvas.Canvas,
bounds image.Rectangle,
rocks ...image.Rectangle,
) (
updatedRegion image.Rectangle,
2023-02-23 18:55:19 -07:00
) {
tiles := shatter.Shatter(bounds, rocks...)
2023-02-23 18:55:19 -07:00
for _, tile := range tiles {
2023-02-26 12:27:38 -07:00
FillRectangle (
canvas.Cut(destination, tile),
source, tile)
updatedRegion = updatedRegion.Union(tile)
2023-02-23 18:55:19 -07:00
}
return
2023-02-23 18:55:19 -07:00
}
// FillColorRectangle fills a rectangle within the destination canvas with a
// solid color.
func FillColorRectangle (
destination canvas.Canvas,
color color.RGBA,
bounds image.Rectangle,
) (
updatedRegion image.Rectangle,
) {
dstData, dstStride := destination.Buffer()
bounds = bounds.Canon().Intersect(destination.Bounds())
if bounds.Empty() { return }
updatedRegion = bounds
for y := bounds.Min.Y; y < bounds.Max.Y; y ++ {
for x := bounds.Min.X; x < bounds.Max.X; x ++ {
dstData[x + y * dstStride] = color
}}
return
}
// FillColorRectangleShatter is like FillColorRectangle, but it does not draw in
// areas specified in "rocks".
func FillColorRectangleShatter (
destination canvas.Canvas,
color color.RGBA,
bounds image.Rectangle,
rocks ...image.Rectangle,
) (
updatedRegion image.Rectangle,
) {
tiles := shatter.Shatter(bounds, rocks...)
for _, tile := range tiles {
FillColorRectangle(destination, color, tile)
updatedRegion = updatedRegion.Union(tile)
}
return
}
// StrokeColorRectangle is similar to FillColorRectangle, but it draws an inset
// outline of the given rectangle instead.
func StrokeColorRectangle (
destination canvas.Canvas,
color color.RGBA,
bounds image.Rectangle,
weight int,
) (
updatedRegion image.Rectangle,
) {
insetBounds := bounds.Inset(weight)
if insetBounds.Empty() {
return FillColorRectangle(destination, color, bounds)
}
return FillColorRectangleShatter(destination, color, bounds, insetBounds)
}