mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-03 00:16:15 +00:00
all: use color.NRGBA in public API
color.RGBA has two problems with regards to using it. First the color values need to be premultiplied, whereas most APIs have non-premultiplied values. This is mainly to preserve color components with low alpha values. Second there are two ways to premultiply with sRGB. One is to premultiply after sRGB conversion, the other is before. This makes using the API more confusing. Using color.NRGBA in sRGB makes it align with CSS.e Signed-off-by: Egon Elbre <egonelbre@gmail.com>
This commit is contained in:
@@ -19,15 +19,16 @@ import (
|
||||
|
||||
var dumpImages = flag.Bool("saveimages", false, "save test images")
|
||||
|
||||
var clearCol = color.RGBA{A: 0xff, R: 0xde, G: 0xad, B: 0xbe}
|
||||
var clearCol = color.NRGBA{A: 0xff, R: 0xde, G: 0xad, B: 0xbe}
|
||||
var clearColExpect = f32color.NRGBAToRGBA(clearCol)
|
||||
|
||||
func TestFramebufferClear(t *testing.T) {
|
||||
b := newBackend(t)
|
||||
sz := image.Point{X: 800, Y: 600}
|
||||
fbo := setupFBO(t, b, sz)
|
||||
img := screenshot(t, fbo, sz)
|
||||
if got := img.RGBAAt(0, 0); got != clearCol {
|
||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
||||
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,14 +44,14 @@ func TestSimpleShader(t *testing.T) {
|
||||
b.BindProgram(p)
|
||||
b.DrawArrays(backend.DrawModeTriangles, 0, 3)
|
||||
img := screenshot(t, fbo, sz)
|
||||
if got := img.RGBAAt(0, 0); got != clearCol {
|
||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
||||
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||
}
|
||||
// Just off the center to catch inverted triangles.
|
||||
cx, cy := 300, 400
|
||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != exp {
|
||||
t.Errorf("got color %v, expected %v", got, exp)
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != f32color.NRGBAToRGBA(exp) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(exp))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,13 +91,13 @@ func TestInputShader(t *testing.T) {
|
||||
b.BindInputLayout(layout)
|
||||
b.DrawArrays(backend.DrawModeTriangles, 0, 3)
|
||||
img := screenshot(t, fbo, sz)
|
||||
if got := img.RGBAAt(0, 0); got != clearCol {
|
||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
||||
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||
}
|
||||
cx, cy := 300, 400
|
||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != exp {
|
||||
t.Errorf("got color %v, expected %v", got, exp)
|
||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != f32color.NRGBAToRGBA(exp) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(exp))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,21 +107,21 @@ func TestFramebuffers(t *testing.T) {
|
||||
fbo1 := newFBO(t, b, sz)
|
||||
fbo2 := newFBO(t, b, sz)
|
||||
var (
|
||||
col1 = color.RGBA{R: 0xad, G: 0xbe, B: 0xef, A: 0xde}
|
||||
col2 = color.RGBA{R: 0xfe, G: 0xba, B: 0xbe, A: 0xca}
|
||||
col1 = color.NRGBA{R: 0xad, G: 0xbe, B: 0xef, A: 0xde}
|
||||
col2 = color.NRGBA{R: 0xfe, G: 0xba, B: 0xbe, A: 0xca}
|
||||
)
|
||||
fcol1, fcol2 := f32color.RGBAFromSRGB(col1), f32color.RGBAFromSRGB(col2)
|
||||
fcol1, fcol2 := f32color.LinearFromSRGB(col1), f32color.LinearFromSRGB(col2)
|
||||
b.BindFramebuffer(fbo1)
|
||||
b.Clear(fcol1.Float32())
|
||||
b.BindFramebuffer(fbo2)
|
||||
b.Clear(fcol2.Float32())
|
||||
img := screenshot(t, fbo1, sz)
|
||||
if got := img.RGBAAt(0, 0); got != col1 {
|
||||
t.Errorf("got color %v, expected %v", got, col1)
|
||||
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col1) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(col1))
|
||||
}
|
||||
img = screenshot(t, fbo2, sz)
|
||||
if got := img.RGBAAt(0, 0); got != col2 {
|
||||
t.Errorf("got color %v, expected %v", got, col2)
|
||||
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col2) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(col2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ func setupFBO(t *testing.T, b backend.Device, size image.Point) backend.Framebuf
|
||||
b.BindFramebuffer(fbo)
|
||||
// ClearColor accepts linear RGBA colors, while 8-bit colors
|
||||
// are in the sRGB color space.
|
||||
col := f32color.RGBAFromSRGB(clearCol)
|
||||
col := f32color.LinearFromSRGB(clearCol)
|
||||
b.Clear(col.Float32())
|
||||
b.ClearDepth(0.0)
|
||||
b.Viewport(0, 0, size.X, size.Y)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/op"
|
||||
"gioui.org/op/clip"
|
||||
"gioui.org/op/paint"
|
||||
@@ -18,7 +19,7 @@ func TestHeadless(t *testing.T) {
|
||||
defer release()
|
||||
|
||||
sz := w.size
|
||||
col := color.RGBA{A: 0xff, R: 0xca, G: 0xfe}
|
||||
col := color.NRGBA{A: 0xff, R: 0xca, G: 0xfe}
|
||||
var ops op.Ops
|
||||
paint.ColorOp{Color: col}.Add(&ops)
|
||||
// Paint only part of the screen to avoid the glClear optimization.
|
||||
@@ -34,8 +35,8 @@ func TestHeadless(t *testing.T) {
|
||||
if isz := img.Bounds().Size(); isz != sz {
|
||||
t.Errorf("got %v screenshot, expected %v", isz, sz)
|
||||
}
|
||||
if got := img.RGBAAt(0, 0); got != col {
|
||||
t.Errorf("got color %v, expected %v", got, col)
|
||||
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col) {
|
||||
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(col))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +44,8 @@ func TestClipping(t *testing.T) {
|
||||
w, release := newTestWindow(t)
|
||||
defer release()
|
||||
|
||||
col := color.RGBA{A: 0xff, R: 0xca, G: 0xfe}
|
||||
col2 := color.RGBA{A: 0xff, R: 0x00, G: 0xfe}
|
||||
col := color.NRGBA{A: 0xff, R: 0xca, G: 0xfe}
|
||||
col2 := color.NRGBA{A: 0xff, R: 0x00, G: 0xfe}
|
||||
var ops op.Ops
|
||||
paint.ColorOp{Color: col}.Add(&ops)
|
||||
clip.RRect{
|
||||
@@ -77,10 +78,10 @@ func TestClipping(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
bg := color.RGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff}
|
||||
bg := color.NRGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff}
|
||||
tests := []struct {
|
||||
x, y int
|
||||
color color.RGBA
|
||||
color color.NRGBA
|
||||
}{
|
||||
{120, 120, col},
|
||||
{130, 130, col2},
|
||||
@@ -88,8 +89,8 @@ func TestClipping(t *testing.T) {
|
||||
{230, 230, bg},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if got := img.RGBAAt(test.x, test.y); got != test.color {
|
||||
t.Errorf("(%d,%d): got color %v, expected %v", test.x, test.y, got, test.color)
|
||||
if got := img.RGBAAt(test.x, test.y); got != f32color.NRGBAToRGBA(test.color) {
|
||||
t.Errorf("(%d,%d): got color %v, expected %v", test.x, test.y, got, f32color.NRGBAToRGBA(test.color))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,9 +100,9 @@ func TestDepth(t *testing.T) {
|
||||
defer release()
|
||||
var ops op.Ops
|
||||
|
||||
blue := color.RGBA{B: 0xFF, A: 0xFF}
|
||||
blue := color.NRGBA{B: 0xFF, A: 0xFF}
|
||||
paint.FillShape(&ops, blue, clip.Rect(image.Rect(0, 0, 50, 100)).Op())
|
||||
red := color.RGBA{R: 0xFF, A: 0xFF}
|
||||
red := color.NRGBA{R: 0xFF, A: 0xFF}
|
||||
paint.FillShape(&ops, red, clip.Rect(image.Rect(0, 0, 100, 50)).Op())
|
||||
if err := w.Frame(&ops); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -118,15 +119,15 @@ func TestDepth(t *testing.T) {
|
||||
}
|
||||
tests := []struct {
|
||||
x, y int
|
||||
color color.RGBA
|
||||
color color.NRGBA
|
||||
}{
|
||||
{25, 25, red},
|
||||
{75, 25, red},
|
||||
{25, 75, blue},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if got := img.RGBAAt(test.x, test.y); got != test.color {
|
||||
t.Errorf("(%d,%d): got color %v, expected %v", test.x, test.y, got, test.color)
|
||||
if got := img.RGBAAt(test.x, test.y); got != f32color.NRGBAToRGBA(test.color) {
|
||||
t.Errorf("(%d,%d): got color %v, expected %v", test.x, test.y, got, f32color.NRGBAToRGBA(test.color))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user