whee back in busineess
This commit is contained in:
12
artist/color.go
Normal file
12
artist/color.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package artist
|
||||
|
||||
import "image/color"
|
||||
|
||||
// Hex creates a color.RGBA value from an RGBA integer value.
|
||||
func Hex (color uint32) (c color.RGBA) {
|
||||
c.A = uint8(color)
|
||||
c.B = uint8(color >> 8)
|
||||
c.G = uint8(color >> 16)
|
||||
c.R = uint8(color >> 24)
|
||||
return
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package patterns
|
||||
import "image"
|
||||
import "image/color"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist/shapes"
|
||||
|
||||
// Uniform is a pattern that draws a solid color.
|
||||
@@ -15,13 +16,5 @@ func (pattern Uniform) Draw (destination canvas.Canvas, clip image.Rectangle) {
|
||||
|
||||
// Uhex creates a new Uniform pattern from an RGBA integer value.
|
||||
func Uhex (color uint32) (uniform Uniform) {
|
||||
return Uniform(hex(color))
|
||||
}
|
||||
|
||||
func hex (color uint32) (c color.RGBA) {
|
||||
c.A = uint8(color)
|
||||
c.B = uint8(color >> 8)
|
||||
c.G = uint8(color >> 16)
|
||||
c.R = uint8(color >> 24)
|
||||
return
|
||||
return Uniform(artist.Hex(color))
|
||||
}
|
||||
|
||||
@@ -5,23 +5,23 @@ import "image"
|
||||
import "image/color"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
|
||||
// FillEllipse draws the content of one canvas onto another, clipped by an
|
||||
// ellipse stretched to the bounds of the source canvas. The offset point
|
||||
// defines where the origin point of the source canvas is positioned in relation
|
||||
// to the origin point of the destination canvas. To prevent the entire source
|
||||
// canvas's bounds from being used, it must be cut with canvas.Cut().
|
||||
// TODO: redo fill ellipse, stroke ellipse, etc. so that it only takes in
|
||||
// destination and source, using the bounds of destination as the bounds of the
|
||||
// ellipse and the bounds of source as the "clipping rectangle". Line up the Min
|
||||
// of both canvases.
|
||||
|
||||
func FillEllipse (
|
||||
destination canvas.Canvas,
|
||||
source canvas.Canvas,
|
||||
offset image.Point,
|
||||
) (
|
||||
updatedRegion image.Rectangle,
|
||||
) {
|
||||
dstData, dstStride := destination.Buffer()
|
||||
srcData, srcStride := source.Buffer()
|
||||
|
||||
bounds := source.Bounds().Intersect(destination.Bounds()).Canon()
|
||||
realBounds := source.Bounds()
|
||||
offset := source.Bounds().Min.Sub(destination.Bounds().Min)
|
||||
bounds := source.Bounds().Sub(offset).Intersect(destination.Bounds())
|
||||
realBounds := destination.Bounds()
|
||||
if bounds.Empty() { return }
|
||||
updatedRegion = bounds
|
||||
|
||||
@@ -30,22 +30,17 @@ func FillEllipse (
|
||||
for point.X = bounds.Min.X; point.X < bounds.Max.X; point.X ++ {
|
||||
if inEllipse(point, realBounds) {
|
||||
offsetPoint := point.Add(offset)
|
||||
dstIndex := offsetPoint.X + (offsetPoint.Y) * dstStride
|
||||
srcIndex := point.X + point.Y * srcStride
|
||||
dstIndex := point.X + point.Y * dstStride
|
||||
srcIndex := offsetPoint.X + offsetPoint.Y * srcStride
|
||||
dstData[dstIndex] = srcData[srcIndex]
|
||||
}
|
||||
}}
|
||||
return
|
||||
}
|
||||
|
||||
// StrokeEllipse is similar to FillEllipse, but it draws an elliptical inset
|
||||
// outline of the source canvas onto the destination canvas. To prevent the
|
||||
// entire source canvas's bounds from being used, it must be cut with
|
||||
// canvas.Cut().
|
||||
func StrokeEllipse (
|
||||
destination canvas.Canvas,
|
||||
source canvas.Canvas,
|
||||
offset image.Point,
|
||||
weight int,
|
||||
) {
|
||||
if weight < 1 { return }
|
||||
@@ -53,7 +48,10 @@ func StrokeEllipse (
|
||||
dstData, dstStride := destination.Buffer()
|
||||
srcData, srcStride := source.Buffer()
|
||||
|
||||
bounds := source.Bounds().Inset(weight - 1)
|
||||
bounds := destination.Bounds().Inset(weight - 1)
|
||||
offset := source.Bounds().Min.Sub(destination.Bounds().Min)
|
||||
realBounds := destination.Bounds()
|
||||
if bounds.Empty() { return }
|
||||
|
||||
context := ellipsePlottingContext {
|
||||
plottingContext: plottingContext {
|
||||
@@ -63,9 +61,9 @@ func StrokeEllipse (
|
||||
srcStride: srcStride,
|
||||
weight: weight,
|
||||
offset: offset,
|
||||
bounds: bounds.Intersect(destination.Bounds()),
|
||||
bounds: realBounds,
|
||||
},
|
||||
radii: image.Pt(bounds.Dx() / 2 - 1, bounds.Dy() / 2 - 1),
|
||||
radii: image.Pt(bounds.Dx() / 2, bounds.Dy() / 2),
|
||||
}
|
||||
context.center = bounds.Min.Add(context.radii)
|
||||
context.plotEllipse()
|
||||
@@ -205,7 +203,7 @@ func StrokeColorEllipse (
|
||||
if weight < 1 { return }
|
||||
|
||||
dstData, dstStride := destination.Buffer()
|
||||
bounds = bounds.Inset(weight - 1)
|
||||
insetBounds := bounds.Inset(weight - 1)
|
||||
|
||||
context := ellipsePlottingContext {
|
||||
plottingContext: plottingContext {
|
||||
@@ -215,9 +213,9 @@ func StrokeColorEllipse (
|
||||
weight: weight,
|
||||
bounds: bounds.Intersect(destination.Bounds()),
|
||||
},
|
||||
radii: image.Pt(bounds.Dx() / 2 - 1, bounds.Dy() / 2 - 1),
|
||||
radii: image.Pt(insetBounds.Dx() / 2, insetBounds.Dy() / 2),
|
||||
}
|
||||
context.center = bounds.Min.Add(context.radii)
|
||||
context.center = insetBounds.Min.Add(context.radii)
|
||||
context.plotEllipse()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -16,32 +16,31 @@ type plottingContext struct {
|
||||
bounds image.Rectangle
|
||||
}
|
||||
|
||||
func (context plottingContext) square (center image.Point) image.Rectangle {
|
||||
func (context plottingContext) square (center image.Point) (square image.Rectangle) {
|
||||
return image.Rect(0, 0, context.weight, context.weight).
|
||||
Sub(image.Pt(context.weight / 2, context.weight / 2)).
|
||||
Add(center).
|
||||
Add(context.offset).
|
||||
Intersect(context.bounds)
|
||||
}
|
||||
|
||||
func (context plottingContext) plotColor (center image.Point) {
|
||||
square := context.square(center)
|
||||
for y := square.Min.Y; y < square.Min.Y; y ++ {
|
||||
for x := square.Min.X; x < square.Min.X; x ++ {
|
||||
for y := square.Min.Y; y < square.Max.Y; y ++ {
|
||||
for x := square.Min.X; x < square.Max.X; x ++ {
|
||||
context.dstData[x + y * context.dstStride] = context.color
|
||||
}}
|
||||
}
|
||||
|
||||
func (context plottingContext) plotSource (center image.Point) {
|
||||
square := context.square(center)
|
||||
for y := square.Min.Y; y < square.Min.Y; y ++ {
|
||||
for x := square.Min.X; x < square.Min.X; x ++ {
|
||||
for y := square.Min.Y; y < square.Max.Y; y ++ {
|
||||
for x := square.Min.X; x < square.Max.X; x ++ {
|
||||
// we offset srcIndex here because we have already applied the
|
||||
// offset to the square, and we need to reverse that to get the
|
||||
// proper source coordinates.
|
||||
srcIndex :=
|
||||
x - context.offset.X +
|
||||
(y - context.offset.Y) * context.dstStride
|
||||
x + context.offset.X +
|
||||
(y + context.offset.Y) * context.dstStride
|
||||
dstIndex := x + y * context.dstStride
|
||||
context.dstData[dstIndex] = context.srcData [srcIndex]
|
||||
}}
|
||||
|
||||
@@ -7,51 +7,44 @@ import "git.tebibyte.media/sashakoshka/tomo/shatter"
|
||||
|
||||
// TODO: return updatedRegion for all routines in this package
|
||||
|
||||
// FillRectangle draws the content of one canvas onto another. The offset point
|
||||
// defines where the origin point of the source canvas is positioned in relation
|
||||
// to the origin point of the destination canvas. To prevent the entire source
|
||||
// canvas from being drawn, it must be cut with canvas.Cut().
|
||||
func FillRectangle (
|
||||
destination canvas.Canvas,
|
||||
source canvas.Canvas,
|
||||
offset image.Point,
|
||||
) (
|
||||
updatedRegion image.Rectangle,
|
||||
) {
|
||||
dstData, dstStride := destination.Buffer()
|
||||
srcData, srcStride := source.Buffer()
|
||||
|
||||
sourceBounds :=
|
||||
source.Bounds().Canon().
|
||||
Intersect(destination.Bounds().Sub(offset))
|
||||
if sourceBounds.Empty() { return }
|
||||
offset := source.Bounds().Min.Sub(destination.Bounds().Min)
|
||||
bounds := source.Bounds().Sub(offset).Intersect(destination.Bounds())
|
||||
if bounds.Empty() { return }
|
||||
updatedRegion = bounds
|
||||
|
||||
updatedRegion = sourceBounds.Add(offset)
|
||||
for y := sourceBounds.Min.Y; y < sourceBounds.Max.Y; y ++ {
|
||||
for x := sourceBounds.Min.X; x < sourceBounds.Max.X; x ++ {
|
||||
dstData[x + offset.X + (y + offset.Y) * dstStride] =
|
||||
srcData[x + y * srcStride]
|
||||
point := image.Point { }
|
||||
for point.Y = bounds.Min.Y; point.Y < bounds.Max.Y; point.Y ++ {
|
||||
for point.X = bounds.Min.X; point.X < bounds.Max.X; point.X ++ {
|
||||
offsetPoint := point.Add(offset)
|
||||
dstIndex := point.X + point.Y * dstStride
|
||||
srcIndex := offsetPoint.X + offsetPoint.Y * srcStride
|
||||
dstData[dstIndex] = srcData[srcIndex]
|
||||
}}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// StrokeRectangle is similar to FillRectangle, but it draws an inset outline of
|
||||
// the source canvas onto the destination canvas. To prevent the entire source
|
||||
// canvas's bounds from being used, it must be cut with canvas.Cut().
|
||||
func StrokeRectangle (
|
||||
destination canvas.Canvas,
|
||||
source canvas.Canvas,
|
||||
offset image.Point,
|
||||
weight int,
|
||||
) {
|
||||
bounds := source.Bounds()
|
||||
bounds := destination.Bounds()
|
||||
insetBounds := bounds.Inset(weight)
|
||||
if insetBounds.Empty() {
|
||||
FillRectangle(destination, source, offset)
|
||||
FillRectangle(destination, source)
|
||||
return
|
||||
}
|
||||
FillRectangleShatter(destination, source, offset, insetBounds)
|
||||
FillRectangleShatter(destination, source, insetBounds)
|
||||
}
|
||||
|
||||
// FillRectangleShatter is like FillRectangle, but it does not draw in areas
|
||||
@@ -59,12 +52,14 @@ func StrokeRectangle (
|
||||
func FillRectangleShatter (
|
||||
destination canvas.Canvas,
|
||||
source canvas.Canvas,
|
||||
offset image.Point,
|
||||
rocks ...image.Rectangle,
|
||||
) {
|
||||
tiles := shatter.Shatter(source.Bounds().Sub(offset), rocks...)
|
||||
tiles := shatter.Shatter(destination.Bounds(), rocks...)
|
||||
offset := source.Bounds().Min.Sub(destination.Bounds().Min)
|
||||
for _, tile := range tiles {
|
||||
FillRectangle(destination, canvas.Cut(source, tile), offset)
|
||||
FillRectangle (
|
||||
canvas.Cut(destination, tile),
|
||||
canvas.Cut(source, tile.Add(offset)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user