WIP texture drawing

This commit is contained in:
Sasha Koshka 2023-08-29 15:52:24 -04:00
parent b5f67c65b0
commit e2a370259b
5 changed files with 71 additions and 14 deletions

10
box.go
View File

@ -17,6 +17,7 @@ type box struct {
bounds image.Rectangle
minSize image.Point
userMinSize image.Point
innerClippingBounds image.Rectangle
minSizeQueued bool
focusQueued *bool
@ -84,7 +85,7 @@ func (this *box) Bounds () image.Rectangle {
}
func (this *box) InnerBounds () image.Rectangle {
return this.padding.Apply(this.innerClippingBounds())
return this.padding.Apply(this.innerClippingBounds)
}
func (this *box) MinimumSize () image.Point {
@ -102,10 +103,6 @@ func (this *box) borderSum () tomo.Inset {
return sum
}
func (this *box) innerClippingBounds () image.Rectangle {
return this.borderSum().Apply(this.bounds)
}
func (this *box) SetBounds (bounds image.Rectangle) {
if this.bounds == bounds { return }
this.bounds = bounds
@ -358,11 +355,12 @@ func (this *box) doDraw () {
if this.canvas == nil { return }
if this.drawer != nil {
this.drawBorders(this.canvas)
this.drawer.Draw(this.canvas.Clip(this.innerClippingBounds()))
this.drawer.Draw(this.canvas.Clip(this.innerClippingBounds))
}
}
func (this *box) doLayout () {
this.innerClippingBounds = this.borderSum().Apply(this.bounds)
if this.parent == nil { this.canvas = nil; return }
parentCanvas := this.parent.canvas()
if parentCanvas == nil { this.canvas = nil; return }

View File

@ -79,9 +79,12 @@ type pen struct {
func (this *pen) Rectangle (bounds image.Rectangle) {
bounds = bounds.Canon()
if this.weight == 0 {
if this.fill.A > 0 {
if this.fill.A > 0 && !this.textureObscures() {
this.fillRectangle(this.fill, bounds)
}
if this.texture != nil {
this.textureRectangle(bounds)
}
} else {
if this.stroke.A > 0 {
this.strokeRectangle(this.stroke, bounds)
@ -115,6 +118,10 @@ func (this *pen) Stroke (stroke color.Color) { this.stroke = convertColor(
func (this *pen) Fill (fill color.Color) { this.fill = convertColor(fill) }
func (this *pen) Texture (texture canvas.Texture) { this.texture = AssertTexture(texture) }
func (this *pen) textureObscures () bool {
return this.texture != nil && this.texture.Opaque()
}
func convertColor (c color.Color) xgraphics.BGRA {
r, g, b, a := c.RGBA()
return xgraphics.BGRA {

View File

@ -4,6 +4,46 @@ import "sort"
import "image"
import "github.com/jezek/xgbutil/xgraphics"
func (this *pen) textureRectangle (bounds image.Rectangle) {
if this.texture.Opaque() {
this.textureRectangleOpaque(bounds)
} else {
this.textureRectangleTransparent(bounds)
}
}
func (this *pen) textureRectangleOpaque (bounds image.Rectangle) {
dstBounds := bounds.Intersect(this.image.Bounds())
srcBounds := this.texture.rect
offset := dstBounds.Min.Sub(bounds.Min)
dstStep := this.image.Stride - bounds.Dx() * 4
srcStep := this.texture.stride - srcBounds.Dx() * 4
}
func (this *pen) textureRectangleTransparent (bounds image.Rectangle) {
bounds = 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)
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
}}
}
func (this *pen) fillRectangle (c xgraphics.BGRA, bounds image.Rectangle) {
if c.A == 255 {
this.fillRectangleOpaque(c, bounds)
@ -227,3 +267,11 @@ func (this *pen) polyLine (c xgraphics.BGRA, points ...image.Point) {
prevPoint = point
}
}
func wrap (n, min, max int) int {
max -= min
n -= min
n %= max
if n < 0 { n += max }
return n + min
}

View File

@ -17,7 +17,7 @@ func NewTextureFrom (source image.Image) *Texture {
bounds := source.Bounds()
texture := &Texture {
pix: make([]uint8, bounds.Dx() * bounds.Dy() * 4),
stride: bounds.Dx(),
stride: bounds.Dx() * 4,
rect: bounds.Sub(bounds.Min),
}
@ -59,6 +59,8 @@ func (this *Texture) Clip (bounds image.Rectangle) canvas.Texture {
return &clipped
}
func (this *Texture) pixOffset
// AssertTexture checks if a given canvas.Texture is a texture from this package.
func AssertTexture (unknown canvas.Texture) *Texture {
if tx, ok := unknown.(*Texture); ok {

View File

@ -132,19 +132,21 @@ func (this *containerBox) SetLayout (layout tomo.Layout) {
func (this *containerBox) Draw (can canvas.Canvas) {
if can == nil { return }
pen := can.Pen()
pen.Fill(this.color)
pen.Texture(this.texture)
rocks := make([]image.Rectangle, len(this.children))
for index, box := range this.children {
rocks[index] = box.Bounds()
}
for _, tile := range canvas.Shatter(this.bounds, rocks...) {
clipped := can.Clip(tile)
if this.transparent() && this.parent != nil {
this.parent.drawBackgroundPart(can.Clip(tile))
this.parent.drawBackgroundPart(clipped)
}
pen.Rectangle(tile)
if clipped == nil { continue }
pen := clipped.Pen()
pen.Fill(this.color)
pen.Texture(this.texture)
pen.Rectangle(this.innerClippingBounds)
}
}
@ -157,7 +159,7 @@ func (this *containerBox) drawBackgroundPart (can canvas.Canvas) {
if this.transparent() && this.parent != nil {
this.parent.drawBackgroundPart(can)
}
pen.Rectangle(can.Bounds())
pen.Rectangle(this.innerClippingBounds)
}
func (this *containerBox) flushActionQueue () {