diff --git a/artist/gradient.go b/artist/gradient.go new file mode 100644 index 0000000..2a7a16d --- /dev/null +++ b/artist/gradient.go @@ -0,0 +1,45 @@ +package artist + +import "image/color" + +// Gradient is a pattern that interpolates between two colors. +type Gradient struct { + First Pattern + Second Pattern + Orientation +} + +// AtWhen satisfies the Pattern interface. +func (pattern Gradient) AtWhen (x, y, width, height int) (c color.RGBA) { + var position float64 + switch pattern.Orientation { + case OrientationVertical: + position = float64(x) / float64(width) + case OrientationDiagonalRight: + position = (float64(x) / float64(width) + + float64(y) / float64(height)) / 2 + case OrientationHorizontal: + position = float64(y) / float64(height) + case OrientationDiagonalLeft: + position = (float64(width - x) / float64(width) + + float64(y) / float64(height)) / 2 + } + + firstColor := pattern.First.AtWhen(x, y, width, height) + secondColor := pattern.Second.AtWhen(x, y, width, height) + return LerpRGBA(firstColor, secondColor, position) +} + +// Lerp linearally interpolates between two integer values. +func Lerp (first, second int, fac float64) (n int) { + return int(float64(first) * (1 - fac) + float64(second) * fac) +} + +// LerpRGBA linearally interpolates between two color.RGBA values. +func LerpRGBA (first, second color.RGBA, fac float64) (c color.RGBA) { + return color.RGBA { + R: uint8(Lerp(int(first.R), int(second.R), fac)), + G: uint8(Lerp(int(first.G), int(second.G), fac)), + B: uint8(Lerp(int(first.G), int(second.B), fac)), + } +} diff --git a/elements/testing/artist.go b/elements/testing/artist.go index 084bda1..1400294 100644 --- a/elements/testing/artist.go +++ b/elements/testing/artist.go @@ -20,7 +20,7 @@ type Artist struct { func NewArtist () (element *Artist) { element = &Artist { } element.Core, element.core = core.NewCore(element) - element.core.SetMinimumSize(400, 480) + element.core.SetMinimumSize(400, 512) return } @@ -28,7 +28,7 @@ func (element *Artist) Resize (width, height int) { element.core.AllocateCanvas(width, height) bounds := element.Bounds() element.cellBounds.Max.X = bounds.Dx() / 4 - element.cellBounds.Max.Y = (bounds.Dy() - 48) / 6 + element.cellBounds.Max.Y = (bounds.Dy() - 48) / 7 drawStart := time.Now() @@ -190,6 +190,18 @@ func (element *Artist) Resize (width, height int) { CellHeight: 23, }, element.cellAt(3, 5)) + + // 0, 6 - 3, 6 + for x := 0; x < 4; x ++ { + artist.FillRectangle ( + element, + artist.Gradient { + First: artist.NewUniform(hex(0xFF0000FF)), + Second: artist.NewUniform(hex(0x0000FFFF)), + Orientation: artist.Orientation(x), + }, + element.cellAt(x, 6)) + } } func (element *Artist) lines (weight int, bounds image.Rectangle) {