2023-01-14 10:41:51 -07:00
|
|
|
package artist
|
|
|
|
|
2023-02-23 12:44:54 -07:00
|
|
|
import "image"
|
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
2023-02-26 20:20:17 -07:00
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/shatter"
|
2023-01-14 10:41:51 -07:00
|
|
|
|
2023-02-23 12:44:54 -07:00
|
|
|
// Pattern is capable of drawing to a canvas within the bounds of a given
|
|
|
|
// clipping rectangle.
|
2023-01-14 10:41:51 -07:00
|
|
|
type Pattern interface {
|
2023-02-23 12:44:54 -07:00
|
|
|
// Draw draws to destination, using the bounds of destination as a width
|
|
|
|
// and height for things like gradients, bevels, etc. The pattern may
|
|
|
|
// not draw outside the union of destination.Bounds() and clip. The
|
|
|
|
// clipping rectangle effectively takes a subset of the pattern. To
|
|
|
|
// change the bounds of the pattern itself, use canvas.Cut() on the
|
|
|
|
// destination before passing it to Draw().
|
|
|
|
Draw (destination canvas.Canvas, clip image.Rectangle)
|
2023-01-14 10:41:51 -07:00
|
|
|
}
|
2023-02-23 13:00:44 -07:00
|
|
|
|
|
|
|
// Draw lets you use several clipping rectangles to draw a pattern.
|
|
|
|
func Draw (
|
|
|
|
destination canvas.Canvas,
|
|
|
|
source Pattern,
|
|
|
|
clips ...image.Rectangle,
|
2023-02-26 20:20:17 -07:00
|
|
|
) (
|
|
|
|
updatedRegion image.Rectangle,
|
2023-02-23 13:00:44 -07:00
|
|
|
) {
|
|
|
|
for _, clip := range clips {
|
|
|
|
source.Draw(destination, clip)
|
2023-02-26 20:20:17 -07:00
|
|
|
updatedRegion = updatedRegion.Union(clip)
|
2023-02-23 13:00:44 -07:00
|
|
|
}
|
2023-02-26 20:20:17 -07:00
|
|
|
return
|
2023-02-23 13:00:44 -07:00
|
|
|
}
|
|
|
|
|
2023-02-26 20:20:17 -07:00
|
|
|
// DrawBounds lets you specify an overall bounding rectangle for drawing a
|
|
|
|
// pattern. The destination is cut to this rectangle.
|
2023-02-23 13:00:44 -07:00
|
|
|
func DrawBounds (
|
|
|
|
destination canvas.Canvas,
|
2023-02-26 20:20:17 -07:00
|
|
|
source Pattern,
|
2023-02-23 13:00:44 -07:00
|
|
|
bounds image.Rectangle,
|
2023-02-26 20:20:17 -07:00
|
|
|
) (
|
|
|
|
updatedRegion image.Rectangle,
|
|
|
|
) {
|
|
|
|
return Draw(canvas.Cut(destination, bounds), source, bounds)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DrawShatter is like an inverse of Draw, drawing nothing in the areas
|
|
|
|
// specified in "rocks".
|
|
|
|
func DrawShatter (
|
|
|
|
destination canvas.Canvas,
|
2023-02-23 13:00:44 -07:00
|
|
|
source Pattern,
|
2023-02-26 20:20:17 -07:00
|
|
|
rocks ...image.Rectangle,
|
|
|
|
) (
|
|
|
|
updatedRegion image.Rectangle,
|
2023-02-23 13:00:44 -07:00
|
|
|
) {
|
2023-02-26 20:56:20 -07:00
|
|
|
tiles := shatter.Shatter(destination.Bounds(), rocks...)
|
|
|
|
return Draw(destination, source, tiles...)
|
2023-02-23 13:00:44 -07:00
|
|
|
}
|
2023-02-23 15:44:53 -07:00
|
|
|
|
|
|
|
// AllocateSample returns a new canvas containing the result of a pattern. The
|
|
|
|
// resulting canvas can be sourced from shape drawing functions. I beg of you
|
|
|
|
// please do not call this every time you need to draw a shape with a pattern on
|
|
|
|
// it because that is horrible and cruel to the computer.
|
|
|
|
func AllocateSample (source Pattern, width, height int) (allocated canvas.Canvas) {
|
|
|
|
allocated = canvas.NewBasicCanvas(width, height)
|
|
|
|
source.Draw(allocated, allocated.Bounds())
|
|
|
|
return
|
|
|
|
}
|