2023-01-08 23:03:19 -07:00
|
|
|
package artist
|
|
|
|
|
|
|
|
import "image"
|
2023-01-20 17:52:35 -07:00
|
|
|
import "image/color"
|
2023-02-01 23:48:16 -07:00
|
|
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
2023-01-08 23:03:19 -07:00
|
|
|
|
2023-01-20 17:52:35 -07:00
|
|
|
// TODO: draw thick lines more efficiently
|
|
|
|
|
2023-01-14 11:40:05 -07:00
|
|
|
// Line draws a line from one point to another with the specified weight and
|
|
|
|
// pattern.
|
2023-01-08 23:03:19 -07:00
|
|
|
func Line (
|
2023-02-01 23:48:16 -07:00
|
|
|
destination canvas.Canvas,
|
2023-01-13 23:54:57 -07:00
|
|
|
source Pattern,
|
2023-01-08 23:03:19 -07:00
|
|
|
weight int,
|
|
|
|
min image.Point,
|
|
|
|
max image.Point,
|
|
|
|
) (
|
|
|
|
updatedRegion image.Rectangle,
|
|
|
|
) {
|
|
|
|
|
|
|
|
updatedRegion = image.Rectangle { Min: min, Max: max }.Canon()
|
|
|
|
updatedRegion.Max.X ++
|
|
|
|
updatedRegion.Max.Y ++
|
2023-01-13 23:54:57 -07:00
|
|
|
width := updatedRegion.Dx()
|
|
|
|
height := updatedRegion.Dy()
|
2023-01-08 23:03:19 -07:00
|
|
|
|
|
|
|
if abs(max.Y - min.Y) <
|
|
|
|
abs(max.X - min.X) {
|
|
|
|
|
|
|
|
if max.X < min.X {
|
|
|
|
temp := min
|
|
|
|
min = max
|
|
|
|
max = temp
|
|
|
|
}
|
2023-01-13 23:54:57 -07:00
|
|
|
lineLow(destination, source, weight, min, max, width, height)
|
2023-01-08 23:03:19 -07:00
|
|
|
} else {
|
|
|
|
|
|
|
|
if max.Y < min.Y {
|
|
|
|
temp := min
|
|
|
|
min = max
|
|
|
|
max = temp
|
|
|
|
}
|
2023-01-13 23:54:57 -07:00
|
|
|
lineHigh(destination, source, weight, min, max, width, height)
|
2023-01-08 23:03:19 -07:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func lineLow (
|
2023-02-01 23:48:16 -07:00
|
|
|
destination canvas.Canvas,
|
2023-01-13 23:54:57 -07:00
|
|
|
source Pattern,
|
2023-01-08 23:03:19 -07:00
|
|
|
weight int,
|
|
|
|
min image.Point,
|
|
|
|
max image.Point,
|
2023-01-13 23:54:57 -07:00
|
|
|
width, height int,
|
2023-01-08 23:03:19 -07:00
|
|
|
) {
|
2023-01-13 23:54:57 -07:00
|
|
|
data, stride := destination.Buffer()
|
2023-01-14 12:05:27 -07:00
|
|
|
bounds := destination.Bounds()
|
2023-01-13 23:54:57 -07:00
|
|
|
|
2023-01-08 23:03:19 -07:00
|
|
|
deltaX := max.X - min.X
|
|
|
|
deltaY := max.Y - min.Y
|
|
|
|
yi := 1
|
|
|
|
|
|
|
|
if deltaY < 0 {
|
|
|
|
yi = -1
|
|
|
|
deltaY *= -1
|
|
|
|
}
|
|
|
|
|
|
|
|
D := (2 * deltaY) - deltaX
|
|
|
|
y := min.Y
|
|
|
|
|
|
|
|
for x := min.X; x < max.X; x ++ {
|
2023-01-14 12:05:27 -07:00
|
|
|
if !(image.Point { x, y }).In(bounds) { break }
|
2023-01-20 17:52:35 -07:00
|
|
|
squareAround(data, stride, source, x, y, width, height, weight)
|
|
|
|
// data[x + y * stride] = source.AtWhen(x, y, width, height)
|
2023-01-08 23:03:19 -07:00
|
|
|
if D > 0 {
|
|
|
|
y += yi
|
|
|
|
D += 2 * (deltaY - deltaX)
|
|
|
|
} else {
|
|
|
|
D += 2 * deltaY
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func lineHigh (
|
2023-02-01 23:48:16 -07:00
|
|
|
destination canvas.Canvas,
|
2023-01-13 23:54:57 -07:00
|
|
|
source Pattern,
|
2023-01-08 23:03:19 -07:00
|
|
|
weight int,
|
|
|
|
min image.Point,
|
|
|
|
max image.Point,
|
2023-01-13 23:54:57 -07:00
|
|
|
width, height int,
|
2023-01-08 23:03:19 -07:00
|
|
|
) {
|
2023-01-13 23:54:57 -07:00
|
|
|
data, stride := destination.Buffer()
|
2023-01-14 12:05:27 -07:00
|
|
|
bounds := destination.Bounds()
|
2023-01-13 23:54:57 -07:00
|
|
|
|
2023-01-08 23:03:19 -07:00
|
|
|
deltaX := max.X - min.X
|
|
|
|
deltaY := max.Y - min.Y
|
|
|
|
xi := 1
|
|
|
|
|
|
|
|
if deltaX < 0 {
|
|
|
|
xi = -1
|
|
|
|
deltaX *= -1
|
|
|
|
}
|
|
|
|
|
|
|
|
D := (2 * deltaX) - deltaY
|
|
|
|
x := min.X
|
|
|
|
|
|
|
|
for y := min.Y; y < max.Y; y ++ {
|
2023-01-14 12:05:27 -07:00
|
|
|
if !(image.Point { x, y }).In(bounds) { break }
|
2023-01-20 17:52:35 -07:00
|
|
|
squareAround(data, stride, source, x, y, width, height, weight)
|
|
|
|
// data[x + y * stride] = source.AtWhen(x, y, width, height)
|
2023-01-08 23:03:19 -07:00
|
|
|
if D > 0 {
|
|
|
|
x += xi
|
|
|
|
D += 2 * (deltaX - deltaY)
|
|
|
|
} else {
|
|
|
|
D += 2 * deltaX
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func abs (in int) (out int) {
|
|
|
|
if in < 0 { in *= -1}
|
|
|
|
out = in
|
|
|
|
return
|
|
|
|
}
|
2023-01-20 17:52:35 -07:00
|
|
|
|
2023-01-24 14:41:12 -07:00
|
|
|
// TODO: this method of doing things sucks and can cause a segfault. we should
|
|
|
|
// not be doing it this way
|
2023-01-20 17:52:35 -07:00
|
|
|
func squareAround (
|
|
|
|
data []color.RGBA,
|
|
|
|
stride int,
|
|
|
|
source Pattern,
|
|
|
|
x, y, patternWidth, patternHeight, diameter int,
|
|
|
|
) {
|
2023-01-20 18:52:06 -07:00
|
|
|
minY := y - diameter + 1
|
|
|
|
minX := x - diameter + 1
|
2023-01-20 17:52:35 -07:00
|
|
|
maxY := y + diameter
|
|
|
|
maxX := x + diameter
|
|
|
|
for y = minY; y < maxY; y ++ {
|
|
|
|
for x = minX; x < maxX; x ++ {
|
|
|
|
data[x + y * stride] =
|
|
|
|
source.AtWhen(x, y, patternWidth, patternHeight)
|
|
|
|
}}
|
|
|
|
}
|