Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa2ef954b2 | |||
| e4fdde3da1 |
@@ -4,9 +4,10 @@ import "git.tebibyte.media/tomo/tomo"
|
|||||||
import "git.tebibyte.media/tomo/backend/style"
|
import "git.tebibyte.media/tomo/backend/style"
|
||||||
|
|
||||||
type styleApplicator struct {
|
type styleApplicator struct {
|
||||||
style *style.Style
|
style *style.Style
|
||||||
role tomo.Role
|
role tomo.Role
|
||||||
rules []style.Rule
|
rules []style.Rule
|
||||||
|
currentSet style.AttrSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *styleApplicator) apply (box anyBox) {
|
func (this *styleApplicator) apply (box anyBox) {
|
||||||
@@ -41,7 +42,18 @@ func (this *styleApplicator) apply (box anyBox) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset an attribute if it is no longer specified
|
||||||
|
if this.currentSet != nil {
|
||||||
|
for kind := range this.currentSet {
|
||||||
|
_, exists := attrs[kind]
|
||||||
|
if !exists {
|
||||||
|
box.unsetAttr(kind, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// apply that list of attributes
|
// apply that list of attributes
|
||||||
|
this.currentSet = attrs
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
box.setAttr(attr, false)
|
box.setAttr(attr, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,3 +132,32 @@ func convertColor (c color.Color) xgraphics.BGRA {
|
|||||||
A: uint8(a >> 8),
|
A: uint8(a >> 8),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For some reason, xgraphics.BGRA does not specify whether or not it uses
|
||||||
|
// premultiplied alpha, and information regarding this is contradictory.
|
||||||
|
// Basically:
|
||||||
|
// - BGRAModel just takes the result of c.RGBA and bit shifts it, without
|
||||||
|
// un-doing the aplha premultiplication that is required by Color.RGBA,
|
||||||
|
// suggesting that xgraphics.BGRA stores alpha-premultiplied color.
|
||||||
|
// - xgraphics.BlendBGRA lerps between dest and src using only the alpha of
|
||||||
|
// src (temporarily converting the colors to fucking floats for some reason)
|
||||||
|
// which seems to suggest that xgraphics.BGRA *does not* store alpha-
|
||||||
|
// premultiplied color.
|
||||||
|
// There is no issues page on xgbutil so we may never get an answer to this
|
||||||
|
// question. However, in this package we just use xgraphics.BGRA to store alpha-
|
||||||
|
// premultiplied color anyway because its way faster, and I would sooner eat
|
||||||
|
// spaghetti with a spoon than convert to and from float64 to blend pixels.
|
||||||
|
func blendPremultipliedBGRA (dst, src xgraphics.BGRA) xgraphics.BGRA {
|
||||||
|
// https://en.wikipedia.org/wiki/Alpha_compositing
|
||||||
|
return xgraphics.BGRA {
|
||||||
|
B: blendPremultipliedChannel(dst.B, src.B, src.A),
|
||||||
|
G: blendPremultipliedChannel(dst.G, src.G, src.A),
|
||||||
|
R: blendPremultipliedChannel(dst.R, src.R, src.A),
|
||||||
|
A: blendPremultipliedChannel(dst.A, src.A, src.A),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func blendPremultipliedChannel (dst, src, a uint8) uint8 {
|
||||||
|
dst16, src16, a16 := uint16(dst), uint16(src), uint16(a)
|
||||||
|
return uint8(src16 + ((dst16 * (255 - a16)) >> 8))
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func (this *pen) textureRectangleTransparent (bounds image.Rectangle) {
|
|||||||
srcPos := pos.Add(offset)
|
srcPos := pos.Add(offset)
|
||||||
dstIndex := this.image.PixOffset(pos.X, pos.Y)
|
dstIndex := this.image.PixOffset(pos.X, pos.Y)
|
||||||
srcIndex := this.texture.PixOffset(srcPos.X, srcPos.Y)
|
srcIndex := this.texture.PixOffset(srcPos.X, srcPos.Y)
|
||||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||||
B: dst[dstIndex + 0],
|
B: dst[dstIndex + 0],
|
||||||
G: dst[dstIndex + 1],
|
G: dst[dstIndex + 1],
|
||||||
R: dst[dstIndex + 2],
|
R: dst[dstIndex + 2],
|
||||||
@@ -93,7 +93,7 @@ func (this *pen) fillRectangleTransparent (c xgraphics.BGRA, bounds image.Rectan
|
|||||||
for pos.Y = bounds.Min.Y; pos.Y < bounds.Max.Y; pos.Y ++ {
|
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 ++ {
|
for pos.X = bounds.Min.X; pos.X < bounds.Max.X; pos.X ++ {
|
||||||
index := this.image.PixOffset(pos.X, pos.Y)
|
index := this.image.PixOffset(pos.X, pos.Y)
|
||||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||||
B: this.image.Pix[index + 0],
|
B: this.image.Pix[index + 0],
|
||||||
G: this.image.Pix[index + 1],
|
G: this.image.Pix[index + 1],
|
||||||
R: this.image.Pix[index + 2],
|
R: this.image.Pix[index + 2],
|
||||||
@@ -256,7 +256,7 @@ func (context *fillingContext) fillPolygonHotTransparent () {
|
|||||||
// fill pixels in between
|
// fill pixels in between
|
||||||
for x := left; x < right; x ++ {
|
for x := left; x < right; x ++ {
|
||||||
index := context.image.PixOffset(x, context.y)
|
index := context.image.PixOffset(x, context.y)
|
||||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||||
B: context.image.Pix[index + 0],
|
B: context.image.Pix[index + 0],
|
||||||
G: context.image.Pix[index + 1],
|
G: context.image.Pix[index + 1],
|
||||||
R: context.image.Pix[index + 2],
|
R: context.image.Pix[index + 2],
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (context plottingContext) plot (center image.Point) {
|
|||||||
for y := square.Min.Y; y < square.Max.Y; y ++ {
|
for y := square.Min.Y; y < square.Max.Y; y ++ {
|
||||||
for x := square.Min.X; x < square.Max.X; x ++ {
|
for x := square.Min.X; x < square.Max.X; x ++ {
|
||||||
index := context.image.PixOffset(x, y)
|
index := context.image.PixOffset(x, y)
|
||||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||||
B: context.image.Pix[index + 0],
|
B: context.image.Pix[index + 0],
|
||||||
G: context.image.Pix[index + 1],
|
G: context.image.Pix[index + 1],
|
||||||
R: context.image.Pix[index + 2],
|
R: context.image.Pix[index + 2],
|
||||||
|
|||||||
Reference in New Issue
Block a user