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"
|
||||
|
||||
type styleApplicator struct {
|
||||
style *style.Style
|
||||
role tomo.Role
|
||||
rules []style.Rule
|
||||
style *style.Style
|
||||
role tomo.Role
|
||||
rules []style.Rule
|
||||
currentSet style.AttrSet
|
||||
}
|
||||
|
||||
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
|
||||
this.currentSet = attrs
|
||||
for _, attr := range attrs {
|
||||
box.setAttr(attr, false)
|
||||
}
|
||||
|
||||
@@ -132,3 +132,32 @@ func convertColor (c color.Color) xgraphics.BGRA {
|
||||
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)
|
||||
dstIndex := this.image.PixOffset(pos.X, pos.Y)
|
||||
srcIndex := this.texture.PixOffset(srcPos.X, srcPos.Y)
|
||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
||||
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||
B: dst[dstIndex + 0],
|
||||
G: dst[dstIndex + 1],
|
||||
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.X = bounds.Min.X; pos.X < bounds.Max.X; pos.X ++ {
|
||||
index := this.image.PixOffset(pos.X, pos.Y)
|
||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
||||
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||
B: this.image.Pix[index + 0],
|
||||
G: this.image.Pix[index + 1],
|
||||
R: this.image.Pix[index + 2],
|
||||
@@ -256,7 +256,7 @@ func (context *fillingContext) fillPolygonHotTransparent () {
|
||||
// fill pixels in between
|
||||
for x := left; x < right; x ++ {
|
||||
index := context.image.PixOffset(x, context.y)
|
||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
||||
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||
B: context.image.Pix[index + 0],
|
||||
G: context.image.Pix[index + 1],
|
||||
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 x := square.Min.X; x < square.Max.X; x ++ {
|
||||
index := context.image.PixOffset(x, y)
|
||||
pixel := xgraphics.BlendBGRA(xgraphics.BGRA {
|
||||
pixel := blendPremultipliedBGRA(xgraphics.BGRA {
|
||||
B: context.image.Pix[index + 0],
|
||||
G: context.image.Pix[index + 1],
|
||||
R: context.image.Pix[index + 2],
|
||||
|
||||
Reference in New Issue
Block a user