mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 01:45:36 +00:00
gpu,internal/ops: decode scene commands directly, not through quads
We're about to let clip.Path use more of the compute renderer features (lines, cubic béziers). This change prepares the gpu package for reading one of several commands types, not just the quadratic béziers of before. The old Quad type is still the basis for the stroking algorithms, but this change moves it into package gpu which is the only user. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+1
-2
@@ -2,7 +2,6 @@ package gpu
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/ops"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type quadSplitter struct {
|
type quadSplitter struct {
|
||||||
@@ -47,7 +46,7 @@ func (qs *quadSplitter) encodeQuadTo(from, ctrl, to f32.Point) {
|
|||||||
encodeQuadTo(data, qs.contour, from, ctrl, to)
|
encodeQuadTo(data, qs.contour, from, ctrl, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qs *quadSplitter) splitAndEncode(quad ops.Quad) {
|
func (qs *quadSplitter) splitAndEncode(quad quadSegment) {
|
||||||
cbnd := f32.Rectangle{
|
cbnd := f32.Rectangle{
|
||||||
Min: quad.From,
|
Min: quad.From,
|
||||||
Max: quad.To,
|
Max: quad.To,
|
||||||
|
|||||||
+2
-3
@@ -11,7 +11,6 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/ops"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func isSolidLine(sty dashOp) bool {
|
func isSolidLine(sty dashOp) bool {
|
||||||
@@ -238,7 +237,7 @@ func (qs strokeQuads) splitAt(contour *uint32, ts ...float64) []strokeQuads {
|
|||||||
|
|
||||||
oi = append(oi, strokeQuad{
|
oi = append(oi, strokeQuad{
|
||||||
contour: *contour,
|
contour: *contour,
|
||||||
quad: ops.Quad{
|
quad: quadSegment{
|
||||||
From: from,
|
From: from,
|
||||||
Ctrl: q1,
|
Ctrl: q1,
|
||||||
To: r0,
|
To: r0,
|
||||||
@@ -256,7 +255,7 @@ func (qs strokeQuads) splitAt(contour *uint32, ts ...float64) []strokeQuads {
|
|||||||
}
|
}
|
||||||
oi = append(oi, strokeQuad{
|
oi = append(oi, strokeQuad{
|
||||||
contour: *contour,
|
contour: *contour,
|
||||||
quad: ops.Quad{
|
quad: quadSegment{
|
||||||
From: r0,
|
From: r0,
|
||||||
Ctrl: r1,
|
Ctrl: r1,
|
||||||
To: r2,
|
To: r2,
|
||||||
|
|||||||
+64
-21
@@ -25,6 +25,7 @@ import (
|
|||||||
"gioui.org/internal/f32color"
|
"gioui.org/internal/f32color"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/internal/ops"
|
"gioui.org/internal/ops"
|
||||||
|
"gioui.org/internal/scene"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
@@ -141,6 +142,10 @@ type dashOp struct {
|
|||||||
dashes []float32
|
dashes []float32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type quadSegment struct {
|
||||||
|
From, Ctrl, To f32.Point
|
||||||
|
}
|
||||||
|
|
||||||
func decodeDashOp(data []byte) dashOp {
|
func decodeDashOp(data []byte) dashOp {
|
||||||
_ = data[5]
|
_ = data[5]
|
||||||
if opconst.OpType(data[0]) != opconst.TypeDash {
|
if opconst.OpType(data[0]) != opconst.TypeDash {
|
||||||
@@ -1340,28 +1345,19 @@ func (d *drawOps) writeVertCache(n int) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transform, split paths as needed, calculate maxY, bounds and create GPU vertices.
|
// transform, split paths as needed, calculate maxY, bounds and create GPU vertices.
|
||||||
func (d *drawOps) buildVerts(aux []byte, tr f32.Affine2D, outline bool, stroke clip.StrokeStyle, dashes dashOp) (verts []byte, bounds f32.Rectangle) {
|
func (d *drawOps) buildVerts(pathData []byte, tr f32.Affine2D, outline bool, stroke clip.StrokeStyle, dashes dashOp) (verts []byte, bounds f32.Rectangle) {
|
||||||
inf := float32(math.Inf(+1))
|
inf := float32(math.Inf(+1))
|
||||||
d.qs.bounds = f32.Rectangle{
|
d.qs.bounds = f32.Rectangle{
|
||||||
Min: f32.Point{X: inf, Y: inf},
|
Min: f32.Point{X: inf, Y: inf},
|
||||||
Max: f32.Point{X: -inf, Y: -inf},
|
Max: f32.Point{X: -inf, Y: -inf},
|
||||||
}
|
}
|
||||||
d.qs.d = d
|
d.qs.d = d
|
||||||
bo := binary.LittleEndian
|
|
||||||
startLength := len(d.vertCache)
|
startLength := len(d.vertCache)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case stroke.Width > 0:
|
case stroke.Width > 0:
|
||||||
// Stroke path.
|
// Stroke path.
|
||||||
quads := make(strokeQuads, 0, 2*len(aux)/(ops.QuadSize+4))
|
quads := decodeToStrokeQuads(pathData)
|
||||||
for len(aux) >= ops.QuadSize+4 {
|
|
||||||
quad := strokeQuad{
|
|
||||||
contour: bo.Uint32(aux),
|
|
||||||
quad: ops.DecodeQuad(aux[4:]),
|
|
||||||
}
|
|
||||||
quads = append(quads, quad)
|
|
||||||
aux = aux[ops.QuadSize+4:]
|
|
||||||
}
|
|
||||||
quads = quads.stroke(stroke, dashes)
|
quads = quads.stroke(stroke, dashes)
|
||||||
for _, quad := range quads {
|
for _, quad := range quads {
|
||||||
d.qs.contour = quad.contour
|
d.qs.contour = quad.contour
|
||||||
@@ -1371,22 +1367,56 @@ func (d *drawOps) buildVerts(aux []byte, tr f32.Affine2D, outline bool, stroke c
|
|||||||
}
|
}
|
||||||
|
|
||||||
case outline:
|
case outline:
|
||||||
// Outline path.
|
decodeToOutlineQuads(&d.qs, tr, pathData)
|
||||||
for len(aux) >= ops.QuadSize+4 {
|
|
||||||
d.qs.contour = bo.Uint32(aux)
|
|
||||||
quad := ops.DecodeQuad(aux[4:])
|
|
||||||
quad = quad.Transform(tr)
|
|
||||||
|
|
||||||
d.qs.splitAndEncode(quad)
|
|
||||||
|
|
||||||
aux = aux[ops.QuadSize+4:]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fillMaxY(d.vertCache[startLength:])
|
fillMaxY(d.vertCache[startLength:])
|
||||||
return d.vertCache[startLength:], d.qs.bounds
|
return d.vertCache[startLength:], d.qs.bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decodeOutlineQuads decodes scene commands, splits them into quadratic béziers
|
||||||
|
// as needed and feeds them to the supplied splitter.
|
||||||
|
func decodeToOutlineQuads(qs *quadSplitter, tr f32.Affine2D, pathData []byte) {
|
||||||
|
for len(pathData) >= scene.CommandSize+4 {
|
||||||
|
qs.contour = bo.Uint32(pathData)
|
||||||
|
cmd := ops.DecodeCommand(pathData[4:])
|
||||||
|
switch cmd.Op() {
|
||||||
|
case scene.OpFillQuad:
|
||||||
|
var q quadSegment
|
||||||
|
q.From, q.Ctrl, q.To = scene.DecodeQuad(cmd)
|
||||||
|
q = q.Transform(tr)
|
||||||
|
qs.splitAndEncode(q)
|
||||||
|
default:
|
||||||
|
panic("unsupported scene command")
|
||||||
|
}
|
||||||
|
pathData = pathData[scene.CommandSize+4:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeToStrokeQuads is like decodeOutlineQuads, except it returns a list of stroke
|
||||||
|
// quads ready to stroke.
|
||||||
|
func decodeToStrokeQuads(pathData []byte) strokeQuads {
|
||||||
|
quads := make(strokeQuads, 0, 2*len(pathData)/(scene.CommandSize+4))
|
||||||
|
for len(pathData) >= scene.CommandSize+4 {
|
||||||
|
contour := bo.Uint32(pathData)
|
||||||
|
cmd := ops.DecodeCommand(pathData[4:])
|
||||||
|
switch cmd.Op() {
|
||||||
|
case scene.OpFillQuad:
|
||||||
|
var q quadSegment
|
||||||
|
q.From, q.Ctrl, q.To = scene.DecodeQuad(cmd)
|
||||||
|
quad := strokeQuad{
|
||||||
|
contour: contour,
|
||||||
|
quad: q,
|
||||||
|
}
|
||||||
|
quads = append(quads, quad)
|
||||||
|
default:
|
||||||
|
panic("unsupported scene command")
|
||||||
|
}
|
||||||
|
pathData = pathData[scene.CommandSize+4:]
|
||||||
|
}
|
||||||
|
return quads
|
||||||
|
}
|
||||||
|
|
||||||
// create GPU vertices for transformed r, find the bounds and establish texture transform.
|
// create GPU vertices for transformed r, find the bounds and establish texture transform.
|
||||||
func (d *drawOps) boundsForTransformedRect(r f32.Rectangle, tr f32.Affine2D) (aux []byte, bnd f32.Rectangle, ptr f32.Affine2D) {
|
func (d *drawOps) boundsForTransformedRect(r f32.Rectangle, tr f32.Affine2D) (aux []byte, bnd f32.Rectangle, ptr f32.Affine2D) {
|
||||||
if isPureOffset(tr) {
|
if isPureOffset(tr) {
|
||||||
@@ -1448,3 +1478,16 @@ func isPureOffset(t f32.Affine2D) bool {
|
|||||||
a, b, _, d, e, _ := t.Elems()
|
a, b, _, d, e, _ := t.Elems()
|
||||||
return a == 1 && b == 0 && d == 0 && e == 1
|
return a == 1 && b == 0 && d == 0 && e == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q quadSegment) Transform(t f32.Affine2D) quadSegment {
|
||||||
|
q.From = t.Transform(q.From)
|
||||||
|
q.Ctrl = t.Transform(q.Ctrl)
|
||||||
|
q.To = t.Transform(q.To)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeQuad(d []byte) (q quadSegment) {
|
||||||
|
cmd := ops.DecodeCommand(d)
|
||||||
|
q.From, q.Ctrl, q.To = scene.DecodeQuad(cmd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
+9
-9
@@ -27,7 +27,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/ops"
|
"gioui.org/internal/scene"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
)
|
)
|
||||||
@@ -43,7 +43,7 @@ const strokeTolerance = 0.01
|
|||||||
|
|
||||||
type strokeQuad struct {
|
type strokeQuad struct {
|
||||||
contour uint32
|
contour uint32
|
||||||
quad ops.Quad
|
quad quadSegment
|
||||||
}
|
}
|
||||||
|
|
||||||
type strokeState struct {
|
type strokeState struct {
|
||||||
@@ -74,7 +74,7 @@ func (qs *strokeQuads) closed() bool {
|
|||||||
func (qs *strokeQuads) lineTo(pt f32.Point) {
|
func (qs *strokeQuads) lineTo(pt f32.Point) {
|
||||||
end := qs.pen()
|
end := qs.pen()
|
||||||
*qs = append(*qs, strokeQuad{
|
*qs = append(*qs, strokeQuad{
|
||||||
quad: ops.Quad{
|
quad: quadSegment{
|
||||||
From: end,
|
From: end,
|
||||||
Ctrl: end.Add(pt).Mul(0.5),
|
Ctrl: end.Add(pt).Mul(0.5),
|
||||||
To: pt,
|
To: pt,
|
||||||
@@ -94,9 +94,9 @@ func (qs *strokeQuads) arc(f1, f2 f32.Point, angle float32) {
|
|||||||
end := len(o.Data())
|
end := len(o.Data())
|
||||||
raw := o.Data()[beg:end]
|
raw := o.Data()[beg:end]
|
||||||
|
|
||||||
for qi := 0; len(raw) >= (ops.QuadSize + 4); qi++ {
|
for qi := 0; len(raw) >= (scene.CommandSize + 4); qi++ {
|
||||||
quad := ops.DecodeQuad(raw[4:])
|
quad := decodeQuad(raw[4:])
|
||||||
raw = raw[ops.QuadSize+4:]
|
raw = raw[scene.CommandSize+4:]
|
||||||
*qs = append(*qs, strokeQuad{
|
*qs = append(*qs, strokeQuad{
|
||||||
quad: quad,
|
quad: quad,
|
||||||
})
|
})
|
||||||
@@ -240,7 +240,7 @@ func (qs *strokeQuads) close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*qs = append(*qs, strokeQuad{
|
*qs = append(*qs, strokeQuad{
|
||||||
quad: ops.Quad{
|
quad: quadSegment{
|
||||||
From: p0,
|
From: p0,
|
||||||
Ctrl: p0.Add(p1).Mul(0.5),
|
Ctrl: p0.Add(p1).Mul(0.5),
|
||||||
To: p1,
|
To: p1,
|
||||||
@@ -293,7 +293,7 @@ func (qs strokeQuads) append(ps strokeQuads) strokeQuads {
|
|||||||
p1 := ps[0].quad.From
|
p1 := ps[0].quad.From
|
||||||
if p0 != p1 && lenPt(p0.Sub(p1)) < strokeTolerance {
|
if p0 != p1 && lenPt(p0.Sub(p1)) < strokeTolerance {
|
||||||
qs = append(qs, strokeQuad{
|
qs = append(qs, strokeQuad{
|
||||||
quad: ops.Quad{
|
quad: quadSegment{
|
||||||
From: p0,
|
From: p0,
|
||||||
Ctrl: p0.Add(p1).Mul(0.5),
|
Ctrl: p0.Add(p1).Mul(0.5),
|
||||||
To: p1,
|
To: p1,
|
||||||
@@ -477,7 +477,7 @@ func (qs *strokeQuads) addLine(p0, ctrl, p1 f32.Point, t, d float32) {
|
|||||||
|
|
||||||
*qs = append(*qs,
|
*qs = append(*qs,
|
||||||
strokeQuad{
|
strokeQuad{
|
||||||
quad: ops.Quad{
|
quad: quadSegment{
|
||||||
From: p0,
|
From: p0,
|
||||||
Ctrl: p0.Add(p1).Mul(0.5),
|
Ctrl: p0.Add(p1).Mul(0.5),
|
||||||
To: p1,
|
To: p1,
|
||||||
|
|||||||
+3
-18
@@ -5,7 +5,6 @@ package ops
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"math"
|
"math"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/byteslice"
|
"gioui.org/internal/byteslice"
|
||||||
@@ -13,24 +12,10 @@ import (
|
|||||||
"gioui.org/internal/scene"
|
"gioui.org/internal/scene"
|
||||||
)
|
)
|
||||||
|
|
||||||
const QuadSize = int(unsafe.Sizeof(scene.Command{}))
|
func DecodeCommand(d []byte) scene.Command {
|
||||||
|
|
||||||
type Quad struct {
|
|
||||||
From, Ctrl, To f32.Point
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q Quad) Transform(t f32.Affine2D) Quad {
|
|
||||||
q.From = t.Transform(q.From)
|
|
||||||
q.Ctrl = t.Transform(q.Ctrl)
|
|
||||||
q.To = t.Transform(q.To)
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeQuad(d []byte) (q Quad) {
|
|
||||||
var cmd scene.Command
|
var cmd scene.Command
|
||||||
copy(byteslice.Slice(cmd[:]), d)
|
copy(byteslice.Uint32(cmd[:]), d)
|
||||||
q.From, q.Ctrl, q.To = scene.DecodeQuad(cmd)
|
return cmd
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeTransform(data []byte) (t f32.Affine2D) {
|
func DecodeTransform(data []byte) (t f32.Affine2D) {
|
||||||
|
|||||||
+35
-26
@@ -7,36 +7,45 @@ package scene
|
|||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Op uint32
|
||||||
|
|
||||||
type Command [sceneElemSize / 4]uint32
|
type Command [sceneElemSize / 4]uint32
|
||||||
|
|
||||||
const sceneElemSize = 36
|
const sceneElemSize = 36
|
||||||
|
|
||||||
// GPU commands from scene.h
|
// GPU commands from scene.h
|
||||||
const (
|
const (
|
||||||
elemNop = iota
|
OpNop Op = iota
|
||||||
elemStrokeLine
|
OpStrokeLine
|
||||||
elemFillLine
|
OpFillLine
|
||||||
elemStrokeQuad
|
OpStrokeQuad
|
||||||
elemFillQuad
|
OpFillQuad
|
||||||
elemStrokeCubic
|
OpStrokeCubic
|
||||||
elemFillCubic
|
OpFillCubic
|
||||||
elemStroke
|
OpStroke
|
||||||
elemFill
|
OpFill
|
||||||
elemLineWidth
|
OpLineWidth
|
||||||
elemTransform
|
OpTransform
|
||||||
elemBeginClip
|
OpBeginClip
|
||||||
elemEndClip
|
OpEndClip
|
||||||
elemFillImage
|
OpFillImage
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const CommandSize = int(unsafe.Sizeof(Command{}))
|
||||||
|
|
||||||
|
func (c Command) Op() Op {
|
||||||
|
return Op(c[0])
|
||||||
|
}
|
||||||
|
|
||||||
func Line(start, end f32.Point, stroke bool, flags uint32) Command {
|
func Line(start, end f32.Point, stroke bool, flags uint32) Command {
|
||||||
tag := uint32(elemFillLine)
|
tag := uint32(OpFillLine)
|
||||||
if stroke {
|
if stroke {
|
||||||
tag = elemStrokeLine
|
tag = uint32(OpStrokeLine)
|
||||||
}
|
}
|
||||||
return Command{
|
return Command{
|
||||||
0: flags<<16 | tag,
|
0: flags<<16 | tag,
|
||||||
@@ -48,9 +57,9 @@ func Line(start, end f32.Point, stroke bool, flags uint32) Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Quad(start, ctrl, end f32.Point, stroke bool) Command {
|
func Quad(start, ctrl, end f32.Point, stroke bool) Command {
|
||||||
tag := uint32(elemFillQuad)
|
tag := uint32(OpFillQuad)
|
||||||
if stroke {
|
if stroke {
|
||||||
tag = elemStrokeQuad
|
tag = uint32(OpStrokeQuad)
|
||||||
}
|
}
|
||||||
return Command{
|
return Command{
|
||||||
0: tag,
|
0: tag,
|
||||||
@@ -66,7 +75,7 @@ func Quad(start, ctrl, end f32.Point, stroke bool) Command {
|
|||||||
func Transform(m f32.Affine2D) Command {
|
func Transform(m f32.Affine2D) Command {
|
||||||
sx, hx, ox, hy, sy, oy := m.Elems()
|
sx, hx, ox, hy, sy, oy := m.Elems()
|
||||||
return Command{
|
return Command{
|
||||||
0: elemTransform,
|
0: uint32(OpTransform),
|
||||||
1: math.Float32bits(sx),
|
1: math.Float32bits(sx),
|
||||||
2: math.Float32bits(hy),
|
2: math.Float32bits(hy),
|
||||||
3: math.Float32bits(hx),
|
3: math.Float32bits(hx),
|
||||||
@@ -78,21 +87,21 @@ func Transform(m f32.Affine2D) Command {
|
|||||||
|
|
||||||
func LineWidth(width float32) Command {
|
func LineWidth(width float32) Command {
|
||||||
return Command{
|
return Command{
|
||||||
0: elemLineWidth,
|
0: uint32(OpLineWidth),
|
||||||
1: math.Float32bits(width),
|
1: math.Float32bits(width),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stroke(col color.RGBA) Command {
|
func Stroke(col color.RGBA) Command {
|
||||||
return Command{
|
return Command{
|
||||||
0: elemStroke,
|
0: uint32(OpStroke),
|
||||||
1: uint32(col.R)<<24 | uint32(col.G)<<16 | uint32(col.B)<<8 | uint32(col.A),
|
1: uint32(col.R)<<24 | uint32(col.G)<<16 | uint32(col.B)<<8 | uint32(col.A),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BeginClip(bbox f32.Rectangle) Command {
|
func BeginClip(bbox f32.Rectangle) Command {
|
||||||
return Command{
|
return Command{
|
||||||
0: elemBeginClip,
|
0: uint32(OpBeginClip),
|
||||||
1: math.Float32bits(bbox.Min.X),
|
1: math.Float32bits(bbox.Min.X),
|
||||||
2: math.Float32bits(bbox.Min.Y),
|
2: math.Float32bits(bbox.Min.Y),
|
||||||
3: math.Float32bits(bbox.Max.X),
|
3: math.Float32bits(bbox.Max.X),
|
||||||
@@ -102,7 +111,7 @@ func BeginClip(bbox f32.Rectangle) Command {
|
|||||||
|
|
||||||
func EndClip(bbox f32.Rectangle) Command {
|
func EndClip(bbox f32.Rectangle) Command {
|
||||||
return Command{
|
return Command{
|
||||||
0: elemEndClip,
|
0: uint32(OpEndClip),
|
||||||
1: math.Float32bits(bbox.Min.X),
|
1: math.Float32bits(bbox.Min.X),
|
||||||
2: math.Float32bits(bbox.Min.Y),
|
2: math.Float32bits(bbox.Min.Y),
|
||||||
3: math.Float32bits(bbox.Max.X),
|
3: math.Float32bits(bbox.Max.X),
|
||||||
@@ -112,20 +121,20 @@ func EndClip(bbox f32.Rectangle) Command {
|
|||||||
|
|
||||||
func Fill(col color.RGBA) Command {
|
func Fill(col color.RGBA) Command {
|
||||||
return Command{
|
return Command{
|
||||||
0: elemFill,
|
0: uint32(OpFill),
|
||||||
1: uint32(col.R)<<24 | uint32(col.G)<<16 | uint32(col.B)<<8 | uint32(col.A),
|
1: uint32(col.R)<<24 | uint32(col.G)<<16 | uint32(col.B)<<8 | uint32(col.A),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FillImage(index int) Command {
|
func FillImage(index int) Command {
|
||||||
return Command{
|
return Command{
|
||||||
0: elemFillImage,
|
0: uint32(OpFillImage),
|
||||||
1: uint32(index),
|
1: uint32(index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeQuad(cmd Command) (from, ctrl, to f32.Point) {
|
func DecodeQuad(cmd Command) (from, ctrl, to f32.Point) {
|
||||||
if cmd[0] != elemFillQuad {
|
if cmd[0] != uint32(OpFillQuad) {
|
||||||
panic("invalid command")
|
panic("invalid command")
|
||||||
}
|
}
|
||||||
from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
|
from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
|
||||||
|
|||||||
+2
-3
@@ -10,7 +10,6 @@ import (
|
|||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/internal/byteslice"
|
"gioui.org/internal/byteslice"
|
||||||
"gioui.org/internal/opconst"
|
"gioui.org/internal/opconst"
|
||||||
"gioui.org/internal/ops"
|
|
||||||
"gioui.org/internal/scene"
|
"gioui.org/internal/scene"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
)
|
)
|
||||||
@@ -154,7 +153,7 @@ func (p *Path) Quad(ctrl, to f32.Point) {
|
|||||||
// QuadTo records a quadratic Bézier from the pen to end
|
// QuadTo records a quadratic Bézier from the pen to end
|
||||||
// with the control point ctrl, with absolute coordinates.
|
// with the control point ctrl, with absolute coordinates.
|
||||||
func (p *Path) QuadTo(ctrl, to f32.Point) {
|
func (p *Path) QuadTo(ctrl, to f32.Point) {
|
||||||
data := p.ops.Write(ops.QuadSize + 4)
|
data := p.ops.Write(scene.CommandSize + 4)
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
bo.PutUint32(data[0:], uint32(p.contour))
|
bo.PutUint32(data[0:], uint32(p.contour))
|
||||||
encodeCommand(data[4:], scene.Quad(p.pen, ctrl, to, false))
|
encodeCommand(data[4:], scene.Quad(p.pen, ctrl, to, false))
|
||||||
@@ -395,5 +394,5 @@ func (o Outline) Op() Op {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func encodeCommand(out []byte, cmd scene.Command) {
|
func encodeCommand(out []byte, cmd scene.Command) {
|
||||||
copy(out, byteslice.Slice(cmd[:]))
|
copy(out, byteslice.Uint32(cmd[:]))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user