Textured rectangles are working (if a bit slow)

This commit is contained in:
Sasha Koshka 2023-08-29 17:23:24 -04:00
parent e2a370259b
commit ab80658cd9
2 changed files with 50 additions and 27 deletions

View File

@ -13,34 +13,53 @@ func (this *pen) textureRectangle (bounds image.Rectangle) {
}
func (this *pen) textureRectangleOpaque (bounds image.Rectangle) {
dstBounds := bounds.Intersect(this.image.Bounds())
srcBounds := this.texture.rect
offset := dstBounds.Min.Sub(bounds.Min)
var pos image.Point
dstStep := this.image.Stride - bounds.Dx() * 4
srcStep := this.texture.stride - srcBounds.Dx() * 4
dst := this.image.Pix
src := this.texture.pix
offset := this.texture.rect.Min.Sub(bounds.Min)
for pos.Y = dstBounds.Min.Y; pos.Y < dstBounds.Max.Y; pos.Y ++ {
for pos.X = dstBounds.Min.X; pos.X < dstBounds.Max.X; pos.X ++ {
srcPos := pos.Add(offset)
dstIndex := this.image.PixOffset(pos.X, pos.Y)
srcIndex := this.texture.PixOffset(srcPos.X, srcPos.Y)
dst[dstIndex + 0] = src[srcIndex + 0]
dst[dstIndex + 1] = src[srcIndex + 1]
dst[dstIndex + 2] = src[srcIndex + 2]
dst[dstIndex + 3] = src[srcIndex + 3]
}}
}
func (this *pen) textureRectangleTransparent (bounds image.Rectangle) {
bounds = bounds.Intersect(this.image.Bounds())
dstBounds := bounds.Intersect(this.image.Bounds())
var pos image.Point
for pos.Y = bounds.Min.Y; pos.Y < bounds.Max.Y; pos.Y ++ {
for pos.X = bounds.Min.X; pos.X < bounds.Max.X; pos.X ++ {
index := this.image.PixOffset(pos.X, pos.Y)
dst := this.image.Pix
src := this.texture.pix
offset := this.texture.rect.Min.Sub(bounds.Min)
for pos.Y = dstBounds.Min.Y; pos.Y < dstBounds.Max.Y; pos.Y ++ {
for pos.X = dstBounds.Min.X; pos.X < dstBounds.Max.X; pos.X ++ {
srcPos := pos.Add(offset)
dstIndex := this.image.PixOffset(pos.X, pos.Y)
srcIndex := this.texture.PixOffset(srcPos.X, srcPos.Y)
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
B: this.image.Pix[index + 0],
G: this.image.Pix[index + 1],
R: this.image.Pix[index + 2],
A: this.image.Pix[index + 3],
}, c)
this.image.Pix[index + 0] = pixel.B
this.image.Pix[index + 1] = pixel.G
this.image.Pix[index + 2] = pixel.R
this.image.Pix[index + 3] = pixel.A
B: dst[dstIndex + 0],
G: dst[dstIndex + 1],
R: dst[dstIndex + 2],
A: dst[dstIndex + 3],
}, xgraphics.BGRA {
B: src[srcIndex + 0],
G: src[srcIndex + 1],
R: src[srcIndex + 2],
A: src[srcIndex + 3],
})
dst[dstIndex + 0] = pixel.B
dst[dstIndex + 1] = pixel.G
dst[dstIndex + 2] = pixel.R
dst[dstIndex + 3] = pixel.A
}}
}
@ -91,7 +110,7 @@ func (this *pen) strokeRectangle (c xgraphics.BGRA, bounds image.Rectangle) {
this.fillRectangle(c, bounds)
return
}
top := image.Rect (
bounds.Min.X,
bounds.Min.Y,
@ -122,7 +141,7 @@ func (this *pen) strokeRectangle (c xgraphics.BGRA, bounds image.Rectangle) {
// the polygon filling algorithm is adapted from:
// https://www.alienryderflex.com/polygon_fill/
// (if you write C like that i will disassemble you)
func (this *pen) fillPolygon (c xgraphics.BGRA, points ...image.Point) {
if len(points) < 3 { return }
@ -183,7 +202,7 @@ func (this *pen) fillPolygon (c xgraphics.BGRA, points ...image.Point) {
context.fillPolygonHotTransparent()
}
}
}
type fillingContext struct {
@ -207,7 +226,7 @@ func (context *fillingContext) fillPolygonHotOpaque () {
// constrain boundaries to image size
if left < context.min { left = context.min }
if right > context.max { right = context.max }
// fill pixels in between
for x := left; x < right; x ++ {
index := context.image.PixOffset(x, context.y)
@ -232,7 +251,7 @@ func (context *fillingContext) fillPolygonHotTransparent () {
// constrain boundaries to image size
if left < context.min { left = context.min }
if right > context.max { right = context.max }
// fill pixels in between
for x := left; x < right; x ++ {
index := context.image.PixOffset(x, context.y)

View File

@ -36,7 +36,7 @@ func NewTextureFrom (source image.Image) *Texture {
texture.transparent = true
}
}}
return texture
}
@ -59,7 +59,11 @@ func (this *Texture) Clip (bounds image.Rectangle) canvas.Texture {
return &clipped
}
func (this *Texture) pixOffset
func (this *Texture) PixOffset (x, y int) int {
x = wrap(x, this.rect.Min.X, this.rect.Max.X)
y = wrap(y, this.rect.Min.Y, this.rect.Max.Y)
return x * 4 + y * this.stride
}
// AssertTexture checks if a given canvas.Texture is a texture from this package.
func AssertTexture (unknown canvas.Texture) *Texture {