mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 08:55:35 +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 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) {
|
func TestFramebufferClear(t *testing.T) {
|
||||||
b := newBackend(t)
|
b := newBackend(t)
|
||||||
sz := image.Point{X: 800, Y: 600}
|
sz := image.Point{X: 800, Y: 600}
|
||||||
fbo := setupFBO(t, b, sz)
|
fbo := setupFBO(t, b, sz)
|
||||||
img := screenshot(t, fbo, sz)
|
img := screenshot(t, fbo, sz)
|
||||||
if got := img.RGBAAt(0, 0); got != clearCol {
|
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,14 +44,14 @@ func TestSimpleShader(t *testing.T) {
|
|||||||
b.BindProgram(p)
|
b.BindProgram(p)
|
||||||
b.DrawArrays(backend.DrawModeTriangles, 0, 3)
|
b.DrawArrays(backend.DrawModeTriangles, 0, 3)
|
||||||
img := screenshot(t, fbo, sz)
|
img := screenshot(t, fbo, sz)
|
||||||
if got := img.RGBAAt(0, 0); got != clearCol {
|
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||||
}
|
}
|
||||||
// Just off the center to catch inverted triangles.
|
// Just off the center to catch inverted triangles.
|
||||||
cx, cy := 300, 400
|
cx, cy := 300, 400
|
||||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != exp {
|
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != f32color.NRGBAToRGBA(exp) {
|
||||||
t.Errorf("got color %v, expected %v", got, 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.BindInputLayout(layout)
|
||||||
b.DrawArrays(backend.DrawModeTriangles, 0, 3)
|
b.DrawArrays(backend.DrawModeTriangles, 0, 3)
|
||||||
img := screenshot(t, fbo, sz)
|
img := screenshot(t, fbo, sz)
|
||||||
if got := img.RGBAAt(0, 0); got != clearCol {
|
if got := img.RGBAAt(0, 0); got != clearColExpect {
|
||||||
t.Errorf("got color %v, expected %v", got, clearCol)
|
t.Errorf("got color %v, expected %v", got, clearColExpect)
|
||||||
}
|
}
|
||||||
cx, cy := 300, 400
|
cx, cy := 300, 400
|
||||||
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
shaderCol := f32color.RGBA{R: .25, G: .55, B: .75, A: 1.0}
|
||||||
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != exp {
|
if got, exp := img.RGBAAt(cx, cy), shaderCol.SRGB(); got != f32color.NRGBAToRGBA(exp) {
|
||||||
t.Errorf("got color %v, expected %v", got, 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)
|
fbo1 := newFBO(t, b, sz)
|
||||||
fbo2 := newFBO(t, b, sz)
|
fbo2 := newFBO(t, b, sz)
|
||||||
var (
|
var (
|
||||||
col1 = color.RGBA{R: 0xad, G: 0xbe, B: 0xef, A: 0xde}
|
col1 = color.NRGBA{R: 0xad, G: 0xbe, B: 0xef, A: 0xde}
|
||||||
col2 = color.RGBA{R: 0xfe, G: 0xba, B: 0xbe, A: 0xca}
|
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.BindFramebuffer(fbo1)
|
||||||
b.Clear(fcol1.Float32())
|
b.Clear(fcol1.Float32())
|
||||||
b.BindFramebuffer(fbo2)
|
b.BindFramebuffer(fbo2)
|
||||||
b.Clear(fcol2.Float32())
|
b.Clear(fcol2.Float32())
|
||||||
img := screenshot(t, fbo1, sz)
|
img := screenshot(t, fbo1, sz)
|
||||||
if got := img.RGBAAt(0, 0); got != col1 {
|
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col1) {
|
||||||
t.Errorf("got color %v, expected %v", got, col1)
|
t.Errorf("got color %v, expected %v", got, f32color.NRGBAToRGBA(col1))
|
||||||
}
|
}
|
||||||
img = screenshot(t, fbo2, sz)
|
img = screenshot(t, fbo2, sz)
|
||||||
if got := img.RGBAAt(0, 0); got != col2 {
|
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col2) {
|
||||||
t.Errorf("got color %v, expected %v", got, 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)
|
b.BindFramebuffer(fbo)
|
||||||
// ClearColor accepts linear RGBA colors, while 8-bit colors
|
// ClearColor accepts linear RGBA colors, while 8-bit colors
|
||||||
// are in the sRGB color space.
|
// are in the sRGB color space.
|
||||||
col := f32color.RGBAFromSRGB(clearCol)
|
col := f32color.LinearFromSRGB(clearCol)
|
||||||
b.Clear(col.Float32())
|
b.Clear(col.Float32())
|
||||||
b.ClearDepth(0.0)
|
b.ClearDepth(0.0)
|
||||||
b.Viewport(0, 0, size.X, size.Y)
|
b.Viewport(0, 0, size.X, size.Y)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
|
"gioui.org/internal/f32color"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
@@ -18,7 +19,7 @@ func TestHeadless(t *testing.T) {
|
|||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
sz := w.size
|
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
|
var ops op.Ops
|
||||||
paint.ColorOp{Color: col}.Add(&ops)
|
paint.ColorOp{Color: col}.Add(&ops)
|
||||||
// Paint only part of the screen to avoid the glClear optimization.
|
// 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 {
|
if isz := img.Bounds().Size(); isz != sz {
|
||||||
t.Errorf("got %v screenshot, expected %v", isz, sz)
|
t.Errorf("got %v screenshot, expected %v", isz, sz)
|
||||||
}
|
}
|
||||||
if got := img.RGBAAt(0, 0); got != col {
|
if got := img.RGBAAt(0, 0); got != f32color.NRGBAToRGBA(col) {
|
||||||
t.Errorf("got color %v, expected %v", got, 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)
|
w, release := newTestWindow(t)
|
||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
col := color.RGBA{A: 0xff, R: 0xca, G: 0xfe}
|
col := color.NRGBA{A: 0xff, R: 0xca, G: 0xfe}
|
||||||
col2 := color.RGBA{A: 0xff, R: 0x00, G: 0xfe}
|
col2 := color.NRGBA{A: 0xff, R: 0x00, G: 0xfe}
|
||||||
var ops op.Ops
|
var ops op.Ops
|
||||||
paint.ColorOp{Color: col}.Add(&ops)
|
paint.ColorOp{Color: col}.Add(&ops)
|
||||||
clip.RRect{
|
clip.RRect{
|
||||||
@@ -77,10 +78,10 @@ func TestClipping(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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 {
|
tests := []struct {
|
||||||
x, y int
|
x, y int
|
||||||
color color.RGBA
|
color color.NRGBA
|
||||||
}{
|
}{
|
||||||
{120, 120, col},
|
{120, 120, col},
|
||||||
{130, 130, col2},
|
{130, 130, col2},
|
||||||
@@ -88,8 +89,8 @@ func TestClipping(t *testing.T) {
|
|||||||
{230, 230, bg},
|
{230, 230, bg},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if got := img.RGBAAt(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, 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()
|
defer release()
|
||||||
var ops op.Ops
|
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())
|
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())
|
paint.FillShape(&ops, red, clip.Rect(image.Rect(0, 0, 100, 50)).Op())
|
||||||
if err := w.Frame(&ops); err != nil {
|
if err := w.Frame(&ops); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -118,15 +119,15 @@ func TestDepth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
x, y int
|
x, y int
|
||||||
color color.RGBA
|
color color.NRGBA
|
||||||
}{
|
}{
|
||||||
{25, 25, red},
|
{25, 25, red},
|
||||||
{75, 25, red},
|
{75, 25, red},
|
||||||
{25, 75, blue},
|
{25, 75, blue},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if got := img.RGBAAt(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, test.color)
|
t.Errorf("(%d,%d): got color %v, expected %v", test.x, test.y, got, f32color.NRGBAToRGBA(test.color))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -78,13 +78,13 @@ type drawState struct {
|
|||||||
// Current paint.ImageOp
|
// Current paint.ImageOp
|
||||||
image imageOpData
|
image imageOpData
|
||||||
// Current paint.ColorOp, if any.
|
// Current paint.ColorOp, if any.
|
||||||
color color.RGBA
|
color color.NRGBA
|
||||||
|
|
||||||
// Current paint.LinearGradientOp.
|
// Current paint.LinearGradientOp.
|
||||||
stop1 f32.Point
|
stop1 f32.Point
|
||||||
stop2 f32.Point
|
stop2 f32.Point
|
||||||
color1 color.RGBA
|
color1 color.NRGBA
|
||||||
color2 color.RGBA
|
color2 color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
type pathOp struct {
|
type pathOp struct {
|
||||||
@@ -138,9 +138,9 @@ type imageOpData struct {
|
|||||||
|
|
||||||
type linearGradientOpData struct {
|
type linearGradientOpData struct {
|
||||||
stop1 f32.Point
|
stop1 f32.Point
|
||||||
color1 color.RGBA
|
color1 color.NRGBA
|
||||||
stop2 f32.Point
|
stop2 f32.Point
|
||||||
color2 color.RGBA
|
color2 color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
func (op *clipOp) decode(data []byte) {
|
func (op *clipOp) decode(data []byte) {
|
||||||
@@ -183,11 +183,11 @@ func decodeImageOp(data []byte, refs []interface{}) imageOpData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeColorOp(data []byte) color.RGBA {
|
func decodeColorOp(data []byte) color.NRGBA {
|
||||||
if opconst.OpType(data[0]) != opconst.TypeColor {
|
if opconst.OpType(data[0]) != opconst.TypeColor {
|
||||||
panic("invalid op")
|
panic("invalid op")
|
||||||
}
|
}
|
||||||
return color.RGBA{
|
return color.NRGBA{
|
||||||
R: data[1],
|
R: data[1],
|
||||||
G: data[2],
|
G: data[2],
|
||||||
B: data[3],
|
B: data[3],
|
||||||
@@ -209,13 +209,13 @@ func decodeLinearGradientOp(data []byte) linearGradientOpData {
|
|||||||
X: math.Float32frombits(bo.Uint32(data[9:])),
|
X: math.Float32frombits(bo.Uint32(data[9:])),
|
||||||
Y: math.Float32frombits(bo.Uint32(data[13:])),
|
Y: math.Float32frombits(bo.Uint32(data[13:])),
|
||||||
},
|
},
|
||||||
color1: color.RGBA{
|
color1: color.NRGBA{
|
||||||
R: data[17+0],
|
R: data[17+0],
|
||||||
G: data[17+1],
|
G: data[17+1],
|
||||||
B: data[17+2],
|
B: data[17+2],
|
||||||
A: data[17+3],
|
A: data[17+3],
|
||||||
},
|
},
|
||||||
color2: color.RGBA{
|
color2: color.NRGBA{
|
||||||
R: data[21+0],
|
R: data[21+0],
|
||||||
G: data[21+1],
|
G: data[21+1],
|
||||||
B: data[21+2],
|
B: data[21+2],
|
||||||
@@ -749,7 +749,7 @@ func (d *drawOps) collect(cache *resourceCache, root *op.Ops, viewport image.Poi
|
|||||||
state := drawState{
|
state := drawState{
|
||||||
clip: clip,
|
clip: clip,
|
||||||
rect: true,
|
rect: true,
|
||||||
color: color.RGBA{A: 0xff},
|
color: color.NRGBA{A: 0xff},
|
||||||
}
|
}
|
||||||
d.collectOps(&d.reader, state)
|
d.collectOps(&d.reader, state)
|
||||||
}
|
}
|
||||||
@@ -930,13 +930,13 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
|
|||||||
switch d.matType {
|
switch d.matType {
|
||||||
case materialColor:
|
case materialColor:
|
||||||
m.material = materialColor
|
m.material = materialColor
|
||||||
m.color = f32color.RGBAFromSRGB(d.color)
|
m.color = f32color.LinearFromSRGB(d.color)
|
||||||
m.opaque = m.color.A == 1.0
|
m.opaque = m.color.A == 1.0
|
||||||
case materialLinearGradient:
|
case materialLinearGradient:
|
||||||
m.material = materialLinearGradient
|
m.material = materialLinearGradient
|
||||||
|
|
||||||
m.color1 = f32color.RGBAFromSRGB(d.color1)
|
m.color1 = f32color.LinearFromSRGB(d.color1)
|
||||||
m.color2 = f32color.RGBAFromSRGB(d.color2)
|
m.color2 = f32color.LinearFromSRGB(d.color2)
|
||||||
m.opaque = m.color1.A == 1.0 && m.color2.A == 1.0
|
m.opaque = m.color1.A == 1.0 && m.color2.A == 1.0
|
||||||
|
|
||||||
m.uvTrans = trans.Mul(gradientSpaceTransform(clip, off, d.stop1, d.stop2))
|
m.uvTrans = trans.Mul(gradientSpaceTransform(clip, off, d.stop1, d.stop2))
|
||||||
|
|||||||
+53
-23
@@ -7,7 +7,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RGBA is a 32 bit floating point linear space color.
|
// RGBA is a 32 bit floating point linear premultiplied color space.
|
||||||
type RGBA struct {
|
type RGBA struct {
|
||||||
R, G, B, A float32
|
R, G, B, A float32
|
||||||
}
|
}
|
||||||
@@ -23,11 +23,14 @@ func (col RGBA) Float32() (r, g, b, a float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SRGBA converts from linear to sRGB color space.
|
// SRGBA converts from linear to sRGB color space.
|
||||||
func (col RGBA) SRGB() color.RGBA {
|
func (col RGBA) SRGB() color.NRGBA {
|
||||||
return color.RGBA{
|
if col.A == 0 {
|
||||||
R: uint8(linearTosRGB(col.R)*255 + .5),
|
return color.NRGBA{}
|
||||||
G: uint8(linearTosRGB(col.G)*255 + .5),
|
}
|
||||||
B: uint8(linearTosRGB(col.B)*255 + .5),
|
return color.NRGBA{
|
||||||
|
R: uint8(linearTosRGB(col.R/col.A)*255 + .5),
|
||||||
|
G: uint8(linearTosRGB(col.G/col.A)*255 + .5),
|
||||||
|
B: uint8(linearTosRGB(col.B/col.A)*255 + .5),
|
||||||
A: uint8(col.A*255 + .5),
|
A: uint8(col.A*255 + .5),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,17 +41,50 @@ func (col RGBA) Opaque() RGBA {
|
|||||||
return col
|
return col
|
||||||
}
|
}
|
||||||
|
|
||||||
// RGBAFromSRGB converts from SRGBA to RGBA.
|
// LinearFromSRGB converts from SRGBA to RGBA.
|
||||||
func RGBAFromSRGB(col color.RGBA) RGBA {
|
func LinearFromSRGB(col color.NRGBA) RGBA {
|
||||||
r, g, b, a := col.RGBA()
|
af := float32(col.A) / 0xFF
|
||||||
return RGBA{
|
return RGBA{
|
||||||
R: sRGBToLinear(float32(r) / 0xffff),
|
R: sRGBToLinear(float32(col.R)/0xff) * af,
|
||||||
G: sRGBToLinear(float32(g) / 0xffff),
|
G: sRGBToLinear(float32(col.G)/0xff) * af,
|
||||||
B: sRGBToLinear(float32(b) / 0xffff),
|
B: sRGBToLinear(float32(col.B)/0xff) * af,
|
||||||
A: float32(a) / 0xFFFF,
|
A: af,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NRGBAToRGBA converts from non-premultiplied sRGB color to premultiplied sRGB color.
|
||||||
|
//
|
||||||
|
// Each component in the result is `sRGBToLinear(c * alpha)`, where `c`
|
||||||
|
// is the linear color.
|
||||||
|
func NRGBAToRGBA(col color.NRGBA) color.RGBA {
|
||||||
|
if col.A == 0xFF {
|
||||||
|
return color.RGBA(col)
|
||||||
|
}
|
||||||
|
c := LinearFromSRGB(col)
|
||||||
|
return color.RGBA{
|
||||||
|
R: uint8(linearTosRGB(c.R)*255 + .5),
|
||||||
|
G: uint8(linearTosRGB(c.G)*255 + .5),
|
||||||
|
B: uint8(linearTosRGB(c.B)*255 + .5),
|
||||||
|
A: col.A,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGBAToNRGBA converts from premultiplied sRGB color to non-premultiplied sRGB color.
|
||||||
|
func RGBAToNRGBA(col color.RGBA) color.NRGBA {
|
||||||
|
if col.A == 0xFF {
|
||||||
|
return color.NRGBA(col)
|
||||||
|
}
|
||||||
|
|
||||||
|
linear := RGBA{
|
||||||
|
R: sRGBToLinear(float32(col.R) / 0xff),
|
||||||
|
G: sRGBToLinear(float32(col.G) / 0xff),
|
||||||
|
B: sRGBToLinear(float32(col.B) / 0xff),
|
||||||
|
A: float32(col.A) / 0xff,
|
||||||
|
}
|
||||||
|
|
||||||
|
return linear.SRGB()
|
||||||
|
}
|
||||||
|
|
||||||
// linearTosRGB transforms color value from linear to sRGB.
|
// linearTosRGB transforms color value from linear to sRGB.
|
||||||
func linearTosRGB(c float32) float32 {
|
func linearTosRGB(c float32) float32 {
|
||||||
// Formula from EXT_sRGB.
|
// Formula from EXT_sRGB.
|
||||||
@@ -74,14 +110,8 @@ func sRGBToLinear(c float32) float32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulAlpha scales all color components by alpha/255.
|
// MulAlpha applies the alpha to the color.
|
||||||
func MulAlpha(c color.RGBA, alpha uint8) color.RGBA {
|
func MulAlpha(c color.NRGBA, alpha uint8) color.NRGBA {
|
||||||
// TODO: Optimize. This is pretty slow.
|
c.A = uint8(uint32(c.A) * uint32(alpha) / 0xFF)
|
||||||
a := float32(alpha) / 255.
|
return c
|
||||||
rgba := RGBAFromSRGB(c)
|
|
||||||
rgba.A *= a
|
|
||||||
rgba.R *= a
|
|
||||||
rgba.G *= a
|
|
||||||
rgba.B *= a
|
|
||||||
return rgba.SRGB()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ func draw1000Circles(gtx layout.Context) {
|
|||||||
op.Offset(f32.Pt(float32(x*10), 0)).Add(ops)
|
op.Offset(f32.Pt(float32(x*10), 0)).Add(ops)
|
||||||
for y := 0; y < 10; y++ {
|
for y := 0; y < 10; y++ {
|
||||||
paint.FillShape(ops,
|
paint.FillShape(ops,
|
||||||
color.RGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120},
|
color.NRGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120},
|
||||||
clip.RRect{Rect: f32.Rect(0, 0, 10, 10), NE: 5, SE: 5, SW: 5, NW: 5}.Op(ops),
|
clip.RRect{Rect: f32.Rect(0, 0, 10, 10), NE: 5, SE: 5, SW: 5, NW: 5}.Op(ops),
|
||||||
)
|
)
|
||||||
op.Offset(f32.Pt(0, float32(100))).Add(ops)
|
op.Offset(f32.Pt(0, float32(100))).Add(ops)
|
||||||
@@ -179,7 +179,7 @@ func draw1000CirclesInstanced(gtx layout.Context) {
|
|||||||
op.Offset(f32.Pt(float32(x*10), 0)).Add(ops)
|
op.Offset(f32.Pt(float32(x*10), 0)).Add(ops)
|
||||||
for y := 0; y < 10; y++ {
|
for y := 0; y < 10; y++ {
|
||||||
pi := op.Push(ops)
|
pi := op.Push(ops)
|
||||||
paint.ColorOp{Color: color.RGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120}}.Add(ops)
|
paint.ColorOp{Color: color.NRGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120}}.Add(ops)
|
||||||
c.Add(ops)
|
c.Add(ops)
|
||||||
pi.Pop()
|
pi.Pop()
|
||||||
op.Offset(f32.Pt(0, float32(100))).Add(ops)
|
op.Offset(f32.Pt(0, float32(100))).Add(ops)
|
||||||
@@ -208,7 +208,7 @@ func drawIndividualShapes(gtx layout.Context, th *material.Theme) chan op.CallOp
|
|||||||
op.Offset(f32.Pt(float32(x*50), 0)).Add(ops)
|
op.Offset(f32.Pt(float32(x*50), 0)).Add(ops)
|
||||||
for y := 0; y < 9; y++ {
|
for y := 0; y < 9; y++ {
|
||||||
paint.FillShape(ops,
|
paint.FillShape(ops,
|
||||||
color.RGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120},
|
color.NRGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120},
|
||||||
clip.RRect{Rect: f32.Rect(0, 0, 25, 25), NE: 10, SE: 10, SW: 10, NW: 10}.Op(ops),
|
clip.RRect{Rect: f32.Rect(0, 0, 25, 25), NE: 10, SE: 10, SW: 10, NW: 10}.Op(ops),
|
||||||
)
|
)
|
||||||
op.Offset(f32.Pt(0, float32(50))).Add(ops)
|
op.Offset(f32.Pt(0, float32(50))).Add(ops)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
func TestPaintRect(t *testing.T) {
|
func TestPaintRect(t *testing.T) {
|
||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.Red)
|
r.expect(0, 0, colornames.Red)
|
||||||
r.expect(49, 0, colornames.Red)
|
r.expect(49, 0, colornames.Red)
|
||||||
@@ -26,7 +26,7 @@ func TestPaintRect(t *testing.T) {
|
|||||||
func TestPaintClippedRect(t *testing.T) {
|
func TestPaintClippedRect(t *testing.T) {
|
||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
clip.RRect{Rect: f32.Rect(25, 25, 60, 60)}.Add(o)
|
clip.RRect{Rect: f32.Rect(25, 25, 60, 60)}.Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(24, 35, colornames.White)
|
r.expect(24, 35, colornames.White)
|
||||||
@@ -41,7 +41,7 @@ func TestPaintClippedCirle(t *testing.T) {
|
|||||||
r := float32(10)
|
r := float32(10)
|
||||||
clip.RRect{Rect: f32.Rect(20, 20, 40, 40), SE: r, SW: r, NW: r, NE: r}.Add(o)
|
clip.RRect{Rect: f32.Rect(20, 20, 40, 40), SE: r, SW: r, NW: r, NE: r}.Add(o)
|
||||||
clip.Rect(image.Rect(0, 0, 30, 50)).Add(o)
|
clip.Rect(image.Rect(0, 0, 30, 50)).Add(o)
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(21, 21, colornames.White)
|
r.expect(21, 21, colornames.White)
|
||||||
r.expect(25, 30, colornames.Red)
|
r.expect(25, 30, colornames.Red)
|
||||||
@@ -70,7 +70,7 @@ func TestPaintArc(t *testing.T) {
|
|||||||
p.Line(f32.Pt(-50, 0))
|
p.Line(f32.Pt(-50, 0))
|
||||||
p.Outline().Add(o)
|
p.Outline().Add(o)
|
||||||
|
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 128, 128)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 128, 128)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(0, 25, colornames.Red)
|
r.expect(0, 25, colornames.Red)
|
||||||
@@ -123,7 +123,7 @@ func TestStrokedPathBevelFlat(t *testing.T) {
|
|||||||
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
|
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(10, 50, colornames.Red)
|
r.expect(10, 50, colornames.Red)
|
||||||
@@ -150,7 +150,7 @@ func TestStrokedPathBevelRound(t *testing.T) {
|
|||||||
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
|
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(10, 50, colornames.Red)
|
r.expect(10, 50, colornames.Red)
|
||||||
@@ -177,7 +177,7 @@ func TestStrokedPathBevelSquare(t *testing.T) {
|
|||||||
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
|
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(10, 50, colornames.Red)
|
r.expect(10, 50, colornames.Red)
|
||||||
@@ -204,7 +204,7 @@ func TestStrokedPathRoundRound(t *testing.T) {
|
|||||||
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
|
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(10, 50, colornames.Red)
|
r.expect(10, 50, colornames.Red)
|
||||||
@@ -232,7 +232,7 @@ func TestStrokedPathFlatMiter(t *testing.T) {
|
|||||||
p.Line(f32.Pt(50, 0))
|
p.Line(f32.Pt(50, 0))
|
||||||
|
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -246,7 +246,7 @@ func TestStrokedPathFlatMiter(t *testing.T) {
|
|||||||
p.Line(f32.Pt(50, 0))
|
p.Line(f32.Pt(50, 0))
|
||||||
|
|
||||||
p.Stroke(2, clip.StrokeStyle{}).Add(o)
|
p.Stroke(2, clip.StrokeStyle{}).Add(o)
|
||||||
paint.Fill(o, colornames.Black)
|
paint.Fill(o, black)
|
||||||
}
|
}
|
||||||
|
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
@@ -277,7 +277,7 @@ func TestStrokedPathFlatMiterInf(t *testing.T) {
|
|||||||
p.Line(f32.Pt(50, 0))
|
p.Line(f32.Pt(50, 0))
|
||||||
|
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -291,7 +291,7 @@ func TestStrokedPathFlatMiterInf(t *testing.T) {
|
|||||||
p.Line(f32.Pt(50, 0))
|
p.Line(f32.Pt(50, 0))
|
||||||
|
|
||||||
p.Stroke(2, clip.StrokeStyle{}).Add(o)
|
p.Stroke(2, clip.StrokeStyle{}).Add(o)
|
||||||
paint.Fill(o, colornames.Black)
|
paint.Fill(o, black)
|
||||||
}
|
}
|
||||||
|
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
@@ -312,7 +312,7 @@ func TestStrokedPathZeroWidth(t *testing.T) {
|
|||||||
p.Line(f32.Pt(50, 0))
|
p.Line(f32.Pt(50, 0))
|
||||||
p.Stroke(width, sty).Add(o)
|
p.Stroke(width, sty).Add(o)
|
||||||
|
|
||||||
paint.Fill(o, colornames.Black)
|
paint.Fill(o, black)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -322,7 +322,7 @@ func TestStrokedPathZeroWidth(t *testing.T) {
|
|||||||
p.Line(f32.Pt(30, 0))
|
p.Line(f32.Pt(30, 0))
|
||||||
p.Stroke(0, sty).Add(o) // width=0, disable stroke
|
p.Stroke(0, sty).Add(o) // width=0, disable stroke
|
||||||
|
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}
|
}
|
||||||
|
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ func TestTransformMacro(t *testing.T) {
|
|||||||
// render the first Stacked item
|
// render the first Stacked item
|
||||||
m1 := op.Record(o)
|
m1 := op.Record(o)
|
||||||
dr := image.Rect(0, 0, 128, 50)
|
dr := image.Rect(0, 0, 128, 50)
|
||||||
paint.FillShape(o, colornames.Black, clip.Rect(dr).Op())
|
paint.FillShape(o, black, clip.Rect(dr).Op())
|
||||||
c1 := m1.Stop()
|
c1 := m1.Stop()
|
||||||
|
|
||||||
// Render the second stacked item
|
// Render the second stacked item
|
||||||
m2 := op.Record(o)
|
m2 := op.Record(o)
|
||||||
paint.ColorOp{Color: colornames.Red}.Add(o)
|
paint.ColorOp{Color: red}.Add(o)
|
||||||
// Simulate a draw text call
|
// Simulate a draw text call
|
||||||
stack := op.Push(o)
|
stack := op.Push(o)
|
||||||
op.Offset(f32.Pt(0, 10)).Add(o)
|
op.Offset(f32.Pt(0, 10)).Add(o)
|
||||||
@@ -62,7 +62,7 @@ func TestTransformMacro(t *testing.T) {
|
|||||||
func TestRepeatedPaintsZ(t *testing.T) {
|
func TestRepeatedPaintsZ(t *testing.T) {
|
||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
// Draw a rectangle
|
// Draw a rectangle
|
||||||
paint.FillShape(o, colornames.Black, clip.Rect(image.Rect(0, 0, 128, 50)).Op())
|
paint.FillShape(o, black, clip.Rect(image.Rect(0, 0, 128, 50)).Op())
|
||||||
|
|
||||||
builder := clip.Path{}
|
builder := clip.Path{}
|
||||||
builder.Begin(o)
|
builder.Begin(o)
|
||||||
@@ -72,7 +72,7 @@ func TestRepeatedPaintsZ(t *testing.T) {
|
|||||||
builder.Line(f32.Pt(-10, 0))
|
builder.Line(f32.Pt(-10, 0))
|
||||||
builder.Line(f32.Pt(0, -10))
|
builder.Line(f32.Pt(0, -10))
|
||||||
builder.Outline().Add(o)
|
builder.Outline().Add(o)
|
||||||
paint.Fill(o, colornames.Red)
|
paint.Fill(o, red)
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(5, 5, colornames.Red)
|
r.expect(5, 5, colornames.Red)
|
||||||
r.expect(11, 15, colornames.Black)
|
r.expect(11, 15, colornames.Black)
|
||||||
@@ -86,11 +86,11 @@ func TestNoClipFromPaint(t *testing.T) {
|
|||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
a := f32.Affine2D{}.Rotate(f32.Pt(20, 20), math.Pi/4)
|
a := f32.Affine2D{}.Rotate(f32.Pt(20, 20), math.Pi/4)
|
||||||
op.Affine(a).Add(o)
|
op.Affine(a).Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(10, 10, 30, 30)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(10, 10, 30, 30)).Op())
|
||||||
a = f32.Affine2D{}.Rotate(f32.Pt(20, 20), -math.Pi/4)
|
a = f32.Affine2D{}.Rotate(f32.Pt(20, 20), -math.Pi/4)
|
||||||
op.Affine(a).Add(o)
|
op.Affine(a).Add(o)
|
||||||
|
|
||||||
paint.FillShape(o, colornames.Black, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
paint.FillShape(o, black, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(1, 1, colornames.Black)
|
r.expect(1, 1, colornames.Black)
|
||||||
r.expect(20, 20, colornames.Black)
|
r.expect(20, 20, colornames.Black)
|
||||||
@@ -195,16 +195,16 @@ func TestNegativeOverlaps(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Gradient struct {
|
type Gradient struct {
|
||||||
From, To color.RGBA
|
From, To color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
var gradients = []Gradient{
|
var gradients = []Gradient{
|
||||||
{From: color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF}, To: color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0xFF}},
|
{From: color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF}, To: color.NRGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0xFF}},
|
||||||
{From: color.RGBA{R: 0x19, G: 0xFF, B: 0x19, A: 0xFF}, To: color.RGBA{R: 0xFF, G: 0x19, B: 0x19, A: 0xFF}},
|
{From: color.NRGBA{R: 0x19, G: 0xFF, B: 0x19, A: 0xFF}, To: color.NRGBA{R: 0xFF, G: 0x19, B: 0x19, A: 0xFF}},
|
||||||
{From: color.RGBA{R: 0xFF, G: 0x19, B: 0x19, A: 0xFF}, To: color.RGBA{R: 0x19, G: 0x19, B: 0xFF, A: 0xFF}},
|
{From: color.NRGBA{R: 0xFF, G: 0x19, B: 0x19, A: 0xFF}, To: color.NRGBA{R: 0x19, G: 0x19, B: 0xFF, A: 0xFF}},
|
||||||
{From: color.RGBA{R: 0x19, G: 0x19, B: 0xFF, A: 0xFF}, To: color.RGBA{R: 0x19, G: 0xFF, B: 0x19, A: 0xFF}},
|
{From: color.NRGBA{R: 0x19, G: 0x19, B: 0xFF, A: 0xFF}, To: color.NRGBA{R: 0x19, G: 0xFF, B: 0x19, A: 0xFF}},
|
||||||
{From: color.RGBA{R: 0x19, G: 0xFF, B: 0xFF, A: 0xFF}, To: color.RGBA{R: 0xFF, G: 0x19, B: 0x19, A: 0xFF}},
|
{From: color.NRGBA{R: 0x19, G: 0xFF, B: 0xFF, A: 0xFF}, To: color.NRGBA{R: 0xFF, G: 0x19, B: 0x19, A: 0xFF}},
|
||||||
{From: color.RGBA{R: 0xFF, G: 0xFF, B: 0x19, A: 0xFF}, To: color.RGBA{R: 0x19, G: 0x19, B: 0xFF, A: 0xFF}},
|
{From: color.NRGBA{R: 0xFF, G: 0xFF, B: 0x19, A: 0xFF}, To: color.NRGBA{R: 0x19, G: 0x19, B: 0xFF, A: 0xFF}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLinearGradient(t *testing.T) {
|
func TestLinearGradient(t *testing.T) {
|
||||||
@@ -236,11 +236,11 @@ func TestLinearGradient(t *testing.T) {
|
|||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
gr := pixelAligned
|
gr := pixelAligned
|
||||||
for _, g := range gradients {
|
for _, g := range gradients {
|
||||||
from := f32color.RGBAFromSRGB(g.From)
|
from := f32color.LinearFromSRGB(g.From)
|
||||||
to := f32color.RGBAFromSRGB(g.To)
|
to := f32color.LinearFromSRGB(g.To)
|
||||||
for _, p := range samples {
|
for _, p := range samples {
|
||||||
exp := lerp(from, to, float32(p)/float32(r.img.Bounds().Dx()-1))
|
exp := lerp(from, to, float32(p)/float32(r.img.Bounds().Dx()-1))
|
||||||
r.expect(p, int(gr.Min.Y+gradienth/2), exp.SRGB())
|
r.expect(p, int(gr.Min.Y+gradienth/2), f32color.NRGBAToRGBA(exp.SRGB()))
|
||||||
}
|
}
|
||||||
gr = gr.Add(f32.Pt(0, gradienth))
|
gr = gr.Add(f32.Pt(0, gradienth))
|
||||||
}
|
}
|
||||||
@@ -251,9 +251,9 @@ func TestLinearGradientAngled(t *testing.T) {
|
|||||||
run(t, func(ops *op.Ops) {
|
run(t, func(ops *op.Ops) {
|
||||||
paint.LinearGradientOp{
|
paint.LinearGradientOp{
|
||||||
Stop1: f32.Pt(64, 64),
|
Stop1: f32.Pt(64, 64),
|
||||||
Color1: colornames.Black,
|
Color1: black,
|
||||||
Stop2: f32.Pt(0, 0),
|
Stop2: f32.Pt(0, 0),
|
||||||
Color2: colornames.Red,
|
Color2: red,
|
||||||
}.Add(ops)
|
}.Add(ops)
|
||||||
st := op.Push(ops)
|
st := op.Push(ops)
|
||||||
clip.Rect(image.Rect(0, 0, 64, 64)).Add(ops)
|
clip.Rect(image.Rect(0, 0, 64, 64)).Add(ops)
|
||||||
@@ -262,9 +262,9 @@ func TestLinearGradientAngled(t *testing.T) {
|
|||||||
|
|
||||||
paint.LinearGradientOp{
|
paint.LinearGradientOp{
|
||||||
Stop1: f32.Pt(64, 64),
|
Stop1: f32.Pt(64, 64),
|
||||||
Color1: colornames.White,
|
Color1: white,
|
||||||
Stop2: f32.Pt(128, 0),
|
Stop2: f32.Pt(128, 0),
|
||||||
Color2: colornames.Green,
|
Color2: green,
|
||||||
}.Add(ops)
|
}.Add(ops)
|
||||||
st = op.Push(ops)
|
st = op.Push(ops)
|
||||||
clip.Rect(image.Rect(64, 0, 128, 64)).Add(ops)
|
clip.Rect(image.Rect(64, 0, 128, 64)).Add(ops)
|
||||||
@@ -273,9 +273,9 @@ func TestLinearGradientAngled(t *testing.T) {
|
|||||||
|
|
||||||
paint.LinearGradientOp{
|
paint.LinearGradientOp{
|
||||||
Stop1: f32.Pt(64, 64),
|
Stop1: f32.Pt(64, 64),
|
||||||
Color1: colornames.Black,
|
Color1: black,
|
||||||
Stop2: f32.Pt(128, 128),
|
Stop2: f32.Pt(128, 128),
|
||||||
Color2: colornames.Blue,
|
Color2: blue,
|
||||||
}.Add(ops)
|
}.Add(ops)
|
||||||
st = op.Push(ops)
|
st = op.Push(ops)
|
||||||
clip.Rect(image.Rect(64, 64, 128, 128)).Add(ops)
|
clip.Rect(image.Rect(64, 64, 128, 128)).Add(ops)
|
||||||
@@ -284,9 +284,9 @@ func TestLinearGradientAngled(t *testing.T) {
|
|||||||
|
|
||||||
paint.LinearGradientOp{
|
paint.LinearGradientOp{
|
||||||
Stop1: f32.Pt(64, 64),
|
Stop1: f32.Pt(64, 64),
|
||||||
Color1: colornames.White,
|
Color1: white,
|
||||||
Stop2: f32.Pt(0, 128),
|
Stop2: f32.Pt(0, 128),
|
||||||
Color2: colornames.Magenta,
|
Color2: magenta,
|
||||||
}.Add(ops)
|
}.Add(ops)
|
||||||
st = op.Push(ops)
|
st = op.Push(ops)
|
||||||
clip.Rect(image.Rect(0, 64, 64, 128)).Add(ops)
|
clip.Rect(image.Rect(0, 64, 64, 128)).Add(ops)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
func TestPaintOffset(t *testing.T) {
|
func TestPaintOffset(t *testing.T) {
|
||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
op.Offset(f32.Pt(10, 20)).Add(o)
|
op.Offset(f32.Pt(10, 20)).Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(59, 30, colornames.Red)
|
r.expect(59, 30, colornames.Red)
|
||||||
@@ -28,7 +28,7 @@ func TestPaintRotate(t *testing.T) {
|
|||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/8)
|
a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/8)
|
||||||
op.Affine(a).Add(o)
|
op.Affine(a).Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(20, 20, 60, 60)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(20, 20, 60, 60)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(40, 40, colornames.Red)
|
r.expect(40, 40, colornames.Red)
|
||||||
r.expect(50, 19, colornames.Red)
|
r.expect(50, 19, colornames.Red)
|
||||||
@@ -41,7 +41,7 @@ func TestPaintShear(t *testing.T) {
|
|||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0)
|
a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0)
|
||||||
op.Affine(a).Add(o)
|
op.Affine(a).Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 40, 40)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 40, 40)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(10, 30, colornames.White)
|
r.expect(10, 30, colornames.White)
|
||||||
})
|
})
|
||||||
@@ -51,7 +51,7 @@ func TestClipPaintOffset(t *testing.T) {
|
|||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Add(o)
|
clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Add(o)
|
||||||
op.Offset(f32.Pt(20, 20)).Add(o)
|
op.Offset(f32.Pt(20, 20)).Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(19, 19, colornames.White)
|
r.expect(19, 19, colornames.White)
|
||||||
@@ -64,7 +64,7 @@ func TestClipOffset(t *testing.T) {
|
|||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
op.Offset(f32.Pt(20, 20)).Add(o)
|
op.Offset(f32.Pt(20, 20)).Add(o)
|
||||||
clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Add(o)
|
clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(0, 0, colornames.White)
|
r.expect(0, 0, colornames.White)
|
||||||
r.expect(29, 29, colornames.White)
|
r.expect(29, 29, colornames.White)
|
||||||
@@ -79,7 +79,7 @@ func TestClipScale(t *testing.T) {
|
|||||||
a := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 2)).Offset(f32.Pt(10, 10))
|
a := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 2)).Offset(f32.Pt(10, 10))
|
||||||
op.Affine(a).Add(o)
|
op.Affine(a).Add(o)
|
||||||
clip.RRect{Rect: f32.Rect(10, 10, 20, 20)}.Add(o)
|
clip.RRect{Rect: f32.Rect(10, 10, 20, 20)}.Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 1000, 1000)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 1000, 1000)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(19+10, 19+10, colornames.White)
|
r.expect(19+10, 19+10, colornames.White)
|
||||||
r.expect(20+10, 20+10, colornames.Red)
|
r.expect(20+10, 20+10, colornames.Red)
|
||||||
@@ -92,7 +92,7 @@ func TestClipRotate(t *testing.T) {
|
|||||||
run(t, func(o *op.Ops) {
|
run(t, func(o *op.Ops) {
|
||||||
op.Affine(f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/4)).Add(o)
|
op.Affine(f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/4)).Add(o)
|
||||||
clip.RRect{Rect: f32.Rect(30, 30, 50, 50)}.Add(o)
|
clip.RRect{Rect: f32.Rect(30, 30, 50, 50)}.Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 40, 100, 100)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 40, 100, 100)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
r.expect(39, 39, colornames.White)
|
r.expect(39, 39, colornames.White)
|
||||||
r.expect(41, 41, colornames.Red)
|
r.expect(41, 41, colornames.Red)
|
||||||
@@ -188,7 +188,7 @@ func TestTransformOrder(t *testing.T) {
|
|||||||
|
|
||||||
c := f32.Affine2D{}.Offset(f32.Pt(-10, -10)).Scale(f32.Point{}, f32.Pt(0.5, 0.5))
|
c := f32.Affine2D{}.Offset(f32.Pt(-10, -10)).Scale(f32.Point{}, f32.Pt(0.5, 0.5))
|
||||||
op.Affine(c).Add(o)
|
op.Affine(c).Add(o)
|
||||||
paint.FillShape(o, colornames.Red, clip.Rect(image.Rect(0, 0, 20, 20)).Op())
|
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 20, 20)).Op())
|
||||||
}, func(r result) {
|
}, func(r result) {
|
||||||
// centered and with radius 40
|
// centered and with radius 40
|
||||||
r.expect(64-41, 64, colornames.White)
|
r.expect(64-41, 64, colornames.White)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"gioui.org/app/headless"
|
"gioui.org/app/headless"
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
|
"gioui.org/internal/f32color"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
"golang.org/x/image/colornames"
|
"golang.org/x/image/colornames"
|
||||||
@@ -25,6 +26,15 @@ var (
|
|||||||
squares paint.ImageOp
|
squares paint.ImageOp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
red = f32color.RGBAToNRGBA(colornames.Red)
|
||||||
|
green = f32color.RGBAToNRGBA(colornames.Green)
|
||||||
|
blue = f32color.RGBAToNRGBA(colornames.Blue)
|
||||||
|
magenta = f32color.RGBAToNRGBA(colornames.Magenta)
|
||||||
|
black = f32color.RGBAToNRGBA(colornames.Black)
|
||||||
|
white = f32color.RGBAToNRGBA(colornames.White)
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// build the texture we use for testing
|
// build the texture we use for testing
|
||||||
size := 512
|
size := 512
|
||||||
|
|||||||
+1
-1
@@ -9,6 +9,6 @@ taking the current transformation into account.
|
|||||||
The current brush is set by either a ColorOp for a constant color, or
|
The current brush is set by either a ColorOp for a constant color, or
|
||||||
ImageOp for an image, or LinearGradientOp for gradients.
|
ImageOp for an image, or LinearGradientOp for gradients.
|
||||||
|
|
||||||
All color.RGBA values are in the sRGB color space.
|
All color.NRGBA values are in the sRGB color space.
|
||||||
*/
|
*/
|
||||||
package paint
|
package paint
|
||||||
|
|||||||
+7
-7
@@ -21,7 +21,7 @@ import (
|
|||||||
// See NewImageOp for details.
|
// See NewImageOp for details.
|
||||||
type ImageOp struct {
|
type ImageOp struct {
|
||||||
uniform bool
|
uniform bool
|
||||||
color color.RGBA
|
color color.NRGBA
|
||||||
src *image.RGBA
|
src *image.RGBA
|
||||||
|
|
||||||
// handle is a key to uniquely identify this ImageOp
|
// handle is a key to uniquely identify this ImageOp
|
||||||
@@ -31,16 +31,16 @@ type ImageOp struct {
|
|||||||
|
|
||||||
// ColorOp sets the brush to a constant color.
|
// ColorOp sets the brush to a constant color.
|
||||||
type ColorOp struct {
|
type ColorOp struct {
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinearGradientOp sets the brush to a gradient starting at stop1 with color1 and
|
// LinearGradientOp sets the brush to a gradient starting at stop1 with color1 and
|
||||||
// ending at stop2 with color2.
|
// ending at stop2 with color2.
|
||||||
type LinearGradientOp struct {
|
type LinearGradientOp struct {
|
||||||
Stop1 f32.Point
|
Stop1 f32.Point
|
||||||
Color1 color.RGBA
|
Color1 color.NRGBA
|
||||||
Stop2 f32.Point
|
Stop2 f32.Point
|
||||||
Color2 color.RGBA
|
Color2 color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaintOp fills fills the current clip area with the current brush.
|
// PaintOp fills fills the current clip area with the current brush.
|
||||||
@@ -58,7 +58,7 @@ type PaintOp struct {
|
|||||||
func NewImageOp(src image.Image) ImageOp {
|
func NewImageOp(src image.Image) ImageOp {
|
||||||
switch src := src.(type) {
|
switch src := src.(type) {
|
||||||
case *image.Uniform:
|
case *image.Uniform:
|
||||||
col := color.RGBAModel.Convert(src.C).(color.RGBA)
|
col := color.NRGBAModel.Convert(src.C).(color.NRGBA)
|
||||||
return ImageOp{
|
return ImageOp{
|
||||||
uniform: true,
|
uniform: true,
|
||||||
color: col,
|
color: col,
|
||||||
@@ -138,7 +138,7 @@ func (d PaintOp) Add(o *op.Ops) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FillShape fills the clip shape with a color.
|
// FillShape fills the clip shape with a color.
|
||||||
func FillShape(ops *op.Ops, c color.RGBA, shape clip.Op) {
|
func FillShape(ops *op.Ops, c color.NRGBA, shape clip.Op) {
|
||||||
defer op.Push(ops).Pop()
|
defer op.Push(ops).Pop()
|
||||||
shape.Add(ops)
|
shape.Add(ops)
|
||||||
Fill(ops, c)
|
Fill(ops, c)
|
||||||
@@ -148,7 +148,7 @@ func FillShape(ops *op.Ops, c color.RGBA, shape clip.Op) {
|
|||||||
// is intended to be used with a clip.Op already in place to limit
|
// is intended to be used with a clip.Op already in place to limit
|
||||||
// the painted area. Use FillShape unless you need to paint several
|
// the painted area. Use FillShape unless you need to paint several
|
||||||
// times within the same clip.Op.
|
// times within the same clip.Op.
|
||||||
func Fill(ops *op.Ops, c color.RGBA) {
|
func Fill(ops *op.Ops, c color.NRGBA) {
|
||||||
defer op.Push(ops).Pop()
|
defer op.Push(ops).Pop()
|
||||||
ColorOp{Color: c}.Add(ops)
|
ColorOp{Color: c}.Add(ops)
|
||||||
PaintOp{}.Add(ops)
|
PaintOp{}.Add(ops)
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
// Border lays out a widget and draws a border inside it.
|
// Border lays out a widget and draws a border inside it.
|
||||||
type Border struct {
|
type Border struct {
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
CornerRadius unit.Value
|
CornerRadius unit.Value
|
||||||
Width unit.Value
|
Width unit.Value
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -7,6 +7,7 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
|
||||||
|
"gioui.org/internal/f32color"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
@@ -14,12 +15,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Icon struct {
|
type Icon struct {
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
src []byte
|
src []byte
|
||||||
// Cached values.
|
// Cached values.
|
||||||
op paint.ImageOp
|
op paint.ImageOp
|
||||||
imgSize int
|
imgSize int
|
||||||
imgColor color.RGBA
|
imgColor color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIcon returns a new Icon from IconVG data.
|
// NewIcon returns a new Icon from IconVG data.
|
||||||
@@ -28,7 +29,7 @@ func NewIcon(data []byte) (*Icon, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Icon{src: data, Color: color.RGBA{A: 0xff}}, nil
|
return &Icon{src: data, Color: color.NRGBA{A: 0xff}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ic *Icon) Layout(gtx layout.Context, sz unit.Value) layout.Dimensions {
|
func (ic *Icon) Layout(gtx layout.Context, sz unit.Value) layout.Dimensions {
|
||||||
@@ -49,7 +50,7 @@ func (ic *Icon) image(sz int) paint.ImageOp {
|
|||||||
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
|
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
|
||||||
var ico iconvg.Rasterizer
|
var ico iconvg.Rasterizer
|
||||||
ico.SetDstImage(img, img.Bounds(), draw.Src)
|
ico.SetDstImage(img, img.Bounds(), draw.Src)
|
||||||
m.Palette[0] = ic.Color
|
m.Palette[0] = f32color.NRGBAToRGBA(ic.Color)
|
||||||
iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
|
iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
|
||||||
Palette: &m.Palette,
|
Palette: &m.Palette,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import (
|
|||||||
type ButtonStyle struct {
|
type ButtonStyle struct {
|
||||||
Text string
|
Text string
|
||||||
// Color is the text color.
|
// Color is the text color.
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
Font text.Font
|
Font text.Font
|
||||||
TextSize unit.Value
|
TextSize unit.Value
|
||||||
Background color.RGBA
|
Background color.NRGBA
|
||||||
CornerRadius unit.Value
|
CornerRadius unit.Value
|
||||||
Inset layout.Inset
|
Inset layout.Inset
|
||||||
Button *widget.Clickable
|
Button *widget.Clickable
|
||||||
@@ -33,15 +33,15 @@ type ButtonStyle struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ButtonLayoutStyle struct {
|
type ButtonLayoutStyle struct {
|
||||||
Background color.RGBA
|
Background color.NRGBA
|
||||||
CornerRadius unit.Value
|
CornerRadius unit.Value
|
||||||
Button *widget.Clickable
|
Button *widget.Clickable
|
||||||
}
|
}
|
||||||
|
|
||||||
type IconButtonStyle struct {
|
type IconButtonStyle struct {
|
||||||
Background color.RGBA
|
Background color.NRGBA
|
||||||
// Color is the icon color.
|
// Color is the icon color.
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
Icon *widget.Icon
|
Icon *widget.Icon
|
||||||
// Size is the icon size.
|
// Size is the icon size.
|
||||||
Size unit.Value
|
Size unit.Value
|
||||||
@@ -272,7 +272,7 @@ func drawInk(gtx layout.Context, c widget.Press) {
|
|||||||
const col = 0.8
|
const col = 0.8
|
||||||
ba, bc := byte(alpha*0xff), byte(col*0xff)
|
ba, bc := byte(alpha*0xff), byte(col*0xff)
|
||||||
defer op.Push(gtx.Ops).Pop()
|
defer op.Push(gtx.Ops).Pop()
|
||||||
rgba := f32color.MulAlpha(color.RGBA{A: 0xff, R: bc, G: bc, B: bc}, ba)
|
rgba := f32color.MulAlpha(color.NRGBA{A: 0xff, R: bc, G: bc, B: bc}, ba)
|
||||||
ink := paint.ColorOp{Color: rgba}
|
ink := paint.ColorOp{Color: rgba}
|
||||||
ink.Add(gtx.Ops)
|
ink.Add(gtx.Ops)
|
||||||
rr := size * .5
|
rr := size * .5
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import (
|
|||||||
|
|
||||||
type checkable struct {
|
type checkable struct {
|
||||||
Label string
|
Label string
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
Font text.Font
|
Font text.Font
|
||||||
TextSize unit.Value
|
TextSize unit.Value
|
||||||
IconColor color.RGBA
|
IconColor color.NRGBA
|
||||||
Size unit.Value
|
Size unit.Value
|
||||||
shaper text.Shaper
|
shaper text.Shaper
|
||||||
checkedStateIcon *widget.Icon
|
checkedStateIcon *widget.Icon
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
// Theme-global parameters: For changing the look of all widgets drawn with a
|
// Theme-global parameters: For changing the look of all widgets drawn with a
|
||||||
// particular theme, adjust the `Theme` fields:
|
// particular theme, adjust the `Theme` fields:
|
||||||
//
|
//
|
||||||
// theme.Color.Primary = color.RGBA{...}
|
// theme.Color.Primary = color.NRGBA{...}
|
||||||
//
|
//
|
||||||
// Widget-local parameters: For changing the look of a particular widget,
|
// Widget-local parameters: For changing the look of a particular widget,
|
||||||
// adjust the widget specific theme object:
|
// adjust the widget specific theme object:
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ type EditorStyle struct {
|
|||||||
Font text.Font
|
Font text.Font
|
||||||
TextSize unit.Value
|
TextSize unit.Value
|
||||||
// Color is the text color.
|
// Color is the text color.
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
// Hint contains the text displayed when the editor is empty.
|
// Hint contains the text displayed when the editor is empty.
|
||||||
Hint string
|
Hint string
|
||||||
// HintColor is the color of hint text.
|
// HintColor is the color of hint text.
|
||||||
HintColor color.RGBA
|
HintColor color.NRGBA
|
||||||
Editor *widget.Editor
|
Editor *widget.Editor
|
||||||
|
|
||||||
shaper text.Shaper
|
shaper text.Shaper
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type LabelStyle struct {
|
|||||||
// Face defines the text style.
|
// Face defines the text style.
|
||||||
Font text.Font
|
Font text.Font
|
||||||
// Color is the text color.
|
// Color is the text color.
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
// Alignment specify the text alignment.
|
// Alignment specify the text alignment.
|
||||||
Alignment text.Alignment
|
Alignment text.Alignment
|
||||||
// MaxLines limits the number of lines. Zero means no limit.
|
// MaxLines limits the number of lines. Zero means no limit.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type LoaderStyle struct {
|
type LoaderStyle struct {
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
func Loader(th *Theme) LoaderStyle {
|
func Loader(th *Theme) LoaderStyle {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ProgressBarStyle struct {
|
type ProgressBarStyle struct {
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
Progress int
|
Progress int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ func ProgressBar(th *Theme, progress int) ProgressBarStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions {
|
func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||||
shader := func(width float32, color color.RGBA) layout.Dimensions {
|
shader := func(width float32, color color.NRGBA) layout.Dimensions {
|
||||||
maxHeight := unit.Dp(4)
|
maxHeight := unit.Dp(4)
|
||||||
rr := float32(gtx.Px(unit.Dp(2)))
|
rr := float32(gtx.Px(unit.Dp(2)))
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func Slider(th *Theme, float *widget.Float, min, max float32) SliderStyle {
|
|||||||
|
|
||||||
type SliderStyle struct {
|
type SliderStyle struct {
|
||||||
Min, Max float32
|
Min, Max float32
|
||||||
Color color.RGBA
|
Color color.NRGBA
|
||||||
Float *widget.Float
|
Float *widget.Float
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import (
|
|||||||
|
|
||||||
type SwitchStyle struct {
|
type SwitchStyle struct {
|
||||||
Color struct {
|
Color struct {
|
||||||
Enabled color.RGBA
|
Enabled color.NRGBA
|
||||||
Disabled color.RGBA
|
Disabled color.NRGBA
|
||||||
}
|
}
|
||||||
Switch *widget.Bool
|
Switch *widget.Bool
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
return layout.Dimensions{Size: dims}
|
return layout.Dimensions{Size: dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawDisc(ops *op.Ops, sz float32, col color.RGBA) {
|
func drawDisc(ops *op.Ops, sz float32, col color.NRGBA) {
|
||||||
defer op.Push(ops).Pop()
|
defer op.Push(ops).Pop()
|
||||||
rr := sz / 2
|
rr := sz / 2
|
||||||
r := f32.Rectangle{Max: f32.Point{X: sz, Y: sz}}
|
r := f32.Rectangle{Max: f32.Point{X: sz, Y: sz}}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
type Theme struct {
|
type Theme struct {
|
||||||
Shaper text.Shaper
|
Shaper text.Shaper
|
||||||
Color struct {
|
Color struct {
|
||||||
Primary color.RGBA
|
Primary color.NRGBA
|
||||||
Text color.RGBA
|
Text color.NRGBA
|
||||||
Hint color.RGBA
|
Hint color.NRGBA
|
||||||
InvText color.RGBA
|
InvText color.NRGBA
|
||||||
}
|
}
|
||||||
TextSize unit.Value
|
TextSize unit.Value
|
||||||
Icon struct {
|
Icon struct {
|
||||||
@@ -53,10 +53,10 @@ func mustIcon(ic *widget.Icon, err error) *widget.Icon {
|
|||||||
return ic
|
return ic
|
||||||
}
|
}
|
||||||
|
|
||||||
func rgb(c uint32) color.RGBA {
|
func rgb(c uint32) color.NRGBA {
|
||||||
return argb(0xff000000 | c)
|
return argb(0xff000000 | c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func argb(c uint32) color.RGBA {
|
func argb(c uint32) color.NRGBA {
|
||||||
return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)}
|
return color.NRGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user