forked from joejulian/gio
ui: split OpImage into OpImage and OpDraw
In preparation for an OpColor (and future OpGradient and similar). Label and Editor no longer take an explicit source image. They draw with the current image. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -66,6 +66,10 @@ type drawOps struct {
|
||||
zimageOps []imageOp
|
||||
pathOps []*pathOp
|
||||
pathOpCache []pathOp
|
||||
|
||||
// Current OpImage image and rect, if any.
|
||||
img image.Image
|
||||
imgRect image.Rectangle
|
||||
}
|
||||
|
||||
type drawState struct {
|
||||
@@ -692,13 +696,18 @@ loop:
|
||||
case ops.TypeImage:
|
||||
var op gdraw.OpImage
|
||||
op.Decode(data, r.Refs)
|
||||
d.img = op.Img
|
||||
d.imgRect = op.Rect
|
||||
case ops.TypeDraw:
|
||||
var op gdraw.OpDraw
|
||||
op.Decode(data, r.Refs)
|
||||
off := t.Transform(f32.Point{})
|
||||
clip := clip.Intersect(op.Rect.Add(off))
|
||||
if clip.Empty() {
|
||||
continue
|
||||
}
|
||||
bounds := boundRectF(clip)
|
||||
mat := materialFor(d.cache, op, off, bounds)
|
||||
mat := d.materialFor(d.cache, op.Rect, off, bounds)
|
||||
if bounds.Min == (image.Point{}) && bounds.Max == d.viewport && mat.opaque && mat.material == materialColor {
|
||||
// The image is a uniform opaque color and takes up the whole screen.
|
||||
// Scrap images up to and including this image and set clear color.
|
||||
@@ -745,16 +754,16 @@ func expandPathOp(p *pathOp, clip image.Rectangle) {
|
||||
}
|
||||
}
|
||||
|
||||
func materialFor(cache *resourceCache, op gdraw.OpImage, off f32.Point, clip image.Rectangle) material {
|
||||
func (d *drawOps) materialFor(cache *resourceCache, rect f32.Rectangle, off f32.Point, clip image.Rectangle) material {
|
||||
var m material
|
||||
if uniform, ok := op.Src.(*image.Uniform); ok {
|
||||
if uniform, ok := d.img.(*image.Uniform); ok {
|
||||
m.material = materialColor
|
||||
m.color = gamma(uniform.RGBA())
|
||||
m.opaque = m.color[3] == 1.0
|
||||
} else {
|
||||
m.material = materialTexture
|
||||
dr := boundRectF(op.Rect.Add(off))
|
||||
sr := op.SrcRect
|
||||
dr := boundRectF(rect.Add(off))
|
||||
sr := d.imgRect
|
||||
if dx := dr.Dx(); dx != 0 {
|
||||
// Don't clip 1 px width sources.
|
||||
if sdx := sr.Dx(); sdx > 1 {
|
||||
@@ -769,16 +778,16 @@ func materialFor(cache *resourceCache, op gdraw.OpImage, off f32.Point, clip ima
|
||||
sr.Max.Y -= ((dr.Max.Y-clip.Max.Y)*sdy + dy/2) / dy
|
||||
}
|
||||
}
|
||||
tex, exists := cache.get(op.Src)
|
||||
tex, exists := cache.get(d.img)
|
||||
if !exists {
|
||||
t := &texture{
|
||||
src: op.Src,
|
||||
src: d.img,
|
||||
}
|
||||
cache.put(op.Src, t)
|
||||
cache.put(d.img, t)
|
||||
tex = t
|
||||
}
|
||||
m.texture = tex.(*texture)
|
||||
m.uvScale, m.uvOffset = texSpaceTransform(sr, op.Src.Bounds().Size())
|
||||
m.uvScale, m.uvOffset = texSpaceTransform(sr, d.img.Bounds().Size())
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
+51
-32
@@ -14,58 +14,77 @@ import (
|
||||
)
|
||||
|
||||
type OpImage struct {
|
||||
Rect f32.Rectangle
|
||||
Src image.Image
|
||||
SrcRect image.Rectangle
|
||||
Img image.Image
|
||||
Rect image.Rectangle
|
||||
}
|
||||
|
||||
type OpDraw struct {
|
||||
Rect f32.Rectangle
|
||||
}
|
||||
|
||||
func (i OpImage) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeImageLen)
|
||||
data[0] = byte(ops.TypeImage)
|
||||
bo := binary.LittleEndian
|
||||
ref := o.Ref(i.Src)
|
||||
ref := o.Ref(i.Img)
|
||||
bo.PutUint32(data[1:], uint32(ref))
|
||||
bo.PutUint32(data[5:], math.Float32bits(i.Rect.Min.X))
|
||||
bo.PutUint32(data[9:], math.Float32bits(i.Rect.Min.Y))
|
||||
bo.PutUint32(data[13:], math.Float32bits(i.Rect.Max.X))
|
||||
bo.PutUint32(data[17:], math.Float32bits(i.Rect.Max.Y))
|
||||
bo.PutUint32(data[21:], uint32(i.SrcRect.Min.X))
|
||||
bo.PutUint32(data[25:], uint32(i.SrcRect.Min.Y))
|
||||
bo.PutUint32(data[29:], uint32(i.SrcRect.Max.X))
|
||||
bo.PutUint32(data[33:], uint32(i.SrcRect.Max.Y))
|
||||
bo.PutUint32(data[5:], uint32(i.Rect.Min.X))
|
||||
bo.PutUint32(data[9:], uint32(i.Rect.Min.Y))
|
||||
bo.PutUint32(data[13:], uint32(i.Rect.Max.X))
|
||||
bo.PutUint32(data[17:], uint32(i.Rect.Max.Y))
|
||||
o.Write(data)
|
||||
}
|
||||
|
||||
func (i *OpImage) Decode(d []byte, refs []interface{}) {
|
||||
func (i *OpImage) Decode(data []byte, refs []interface{}) {
|
||||
bo := binary.LittleEndian
|
||||
if ops.OpType(d[0]) != ops.TypeImage {
|
||||
if ops.OpType(data[0]) != ops.TypeImage {
|
||||
panic("invalid op")
|
||||
}
|
||||
ref := int(bo.Uint32(d[1:]))
|
||||
r := f32.Rectangle{
|
||||
Min: f32.Point{
|
||||
X: math.Float32frombits(bo.Uint32(d[5:])),
|
||||
Y: math.Float32frombits(bo.Uint32(d[9:])),
|
||||
},
|
||||
Max: f32.Point{
|
||||
X: math.Float32frombits(bo.Uint32(d[13:])),
|
||||
Y: math.Float32frombits(bo.Uint32(d[17:])),
|
||||
},
|
||||
}
|
||||
ref := int(bo.Uint32(data[1:]))
|
||||
sr := image.Rectangle{
|
||||
Min: image.Point{
|
||||
X: int(bo.Uint32(d[21:])),
|
||||
Y: int(bo.Uint32(d[25:])),
|
||||
X: int(bo.Uint32(data[5:])),
|
||||
Y: int(bo.Uint32(data[9:])),
|
||||
},
|
||||
Max: image.Point{
|
||||
X: int(bo.Uint32(d[29:])),
|
||||
Y: int(bo.Uint32(d[33:])),
|
||||
X: int(bo.Uint32(data[13:])),
|
||||
Y: int(bo.Uint32(data[17:])),
|
||||
},
|
||||
}
|
||||
*i = OpImage{
|
||||
Rect: r,
|
||||
Src: refs[ref].(image.Image),
|
||||
SrcRect: sr,
|
||||
Img: refs[ref].(image.Image),
|
||||
Rect: sr,
|
||||
}
|
||||
}
|
||||
|
||||
func (d OpDraw) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeDrawLen)
|
||||
data[0] = byte(ops.TypeDraw)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], math.Float32bits(d.Rect.Min.X))
|
||||
bo.PutUint32(data[5:], math.Float32bits(d.Rect.Min.Y))
|
||||
bo.PutUint32(data[9:], math.Float32bits(d.Rect.Max.X))
|
||||
bo.PutUint32(data[13:], math.Float32bits(d.Rect.Max.Y))
|
||||
o.Write(data)
|
||||
}
|
||||
|
||||
func (d *OpDraw) Decode(data []byte, refs []interface{}) {
|
||||
bo := binary.LittleEndian
|
||||
if ops.OpType(data[0]) != ops.TypeDraw {
|
||||
panic("invalid op")
|
||||
}
|
||||
r := f32.Rectangle{
|
||||
Min: f32.Point{
|
||||
X: math.Float32frombits(bo.Uint32(data[1:])),
|
||||
Y: math.Float32frombits(bo.Uint32(data[5:])),
|
||||
},
|
||||
Max: f32.Point{
|
||||
X: math.Float32frombits(bo.Uint32(data[9:])),
|
||||
Y: math.Float32frombits(bo.Uint32(data[13:])),
|
||||
},
|
||||
}
|
||||
*d = OpDraw{
|
||||
Rect: r,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ const (
|
||||
TypeRedraw
|
||||
TypeClip
|
||||
TypeImage
|
||||
TypeDraw
|
||||
TypePointerHandler
|
||||
TypeKeyHandler
|
||||
TypeHideInput
|
||||
@@ -42,7 +43,8 @@ const (
|
||||
TypeLayerLen = 1
|
||||
TypeRedrawLen = 1 + 8
|
||||
TypeClipLen = 1 + 4
|
||||
TypeImageLen = 1 + 4 + 4*4 + 4*4
|
||||
TypeImageLen = 1 + 4 + 4*4
|
||||
TypeDrawLen = 1 + 4*4
|
||||
TypePointerHandlerLen = 1 + 4 + 4 + 1
|
||||
TypeKeyHandlerLen = 1 + 4 + 1
|
||||
TypeHideInputLen = 1
|
||||
@@ -58,6 +60,7 @@ var typeLengths = [...]int{
|
||||
TypeRedrawLen,
|
||||
TypeClipLen,
|
||||
TypeImageLen,
|
||||
TypeDrawLen,
|
||||
TypePointerHandlerLen,
|
||||
TypeKeyHandlerLen,
|
||||
TypeHideInputLen,
|
||||
|
||||
+2
-4
@@ -20,7 +20,6 @@ import (
|
||||
)
|
||||
|
||||
type Editor struct {
|
||||
Src image.Image
|
||||
Face Face
|
||||
Alignment Alignment
|
||||
SingleLine bool
|
||||
@@ -175,7 +174,7 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||
ops.Begin()
|
||||
ui.OpTransform{Transform: ui.Offset(lineOff)}.Add(ops)
|
||||
draw.OpClip{Path: path}.Add(ops)
|
||||
draw.OpImage{Rect: toRectF(clip).Sub(lineOff), Src: e.Src, SrcRect: e.Src.Bounds()}.Add(ops)
|
||||
draw.OpDraw{Rect: toRectF(clip).Sub(lineOff)}.Add(ops)
|
||||
ops.End().Add(ops)
|
||||
}
|
||||
if e.focused {
|
||||
@@ -199,8 +198,7 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||
})
|
||||
carRect = clip.Intersect(carRect)
|
||||
if !carRect.Empty() {
|
||||
img := draw.OpImage{Src: e.Src, Rect: toRectF(carRect), SrcRect: e.Src.Bounds()}
|
||||
img.Add(ops)
|
||||
draw.OpDraw{Rect: toRectF(carRect)}.Add(ops)
|
||||
}
|
||||
}
|
||||
if blinking {
|
||||
|
||||
+1
-2
@@ -17,7 +17,6 @@ import (
|
||||
|
||||
type Label struct {
|
||||
Face Face
|
||||
Src image.Image
|
||||
Alignment Alignment
|
||||
Text string
|
||||
|
||||
@@ -106,7 +105,7 @@ func (l Label) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||
ops.Begin()
|
||||
ui.OpTransform{Transform: ui.Offset(off)}.Add(ops)
|
||||
draw.OpClip{Path: path}.Add(ops)
|
||||
draw.OpImage{Rect: lclip, Src: l.Src, SrcRect: l.Src.Bounds()}.Add(ops)
|
||||
draw.OpDraw{Rect: lclip}.Add(ops)
|
||||
ops.End().Add(ops)
|
||||
}
|
||||
return dims
|
||||
|
||||
+2
-1
@@ -27,6 +27,7 @@ func (im Image) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||
dr := f32.Rectangle{
|
||||
Max: f32.Point{X: float32(d.X), Y: float32(d.Y)},
|
||||
}
|
||||
draw.OpImage{Rect: dr, Src: im.Src, SrcRect: im.Rect}.Add(ops)
|
||||
draw.OpImage{Img: im.Src, Rect: im.Rect}.Add(ops)
|
||||
draw.OpDraw{Rect: dr}.Add(ops)
|
||||
return layout.Dimens{Size: d, Baseline: d.Y}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user