123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- // SPDX-License-Identifier: Unlicense OR MIT
- // Package scene encodes and decodes graphics commands in the format used by the
- // compute renderer.
- package scene
- import (
- "fmt"
- "image"
- "image/color"
- "math"
- "unsafe"
- "gioui.org/internal/f32"
- )
- type Op uint32
- type Command [sceneElemSize / 4]uint32
- // GPU commands from piet/scene.h in package gioui.org/shaders.
- const (
- OpNop Op = iota
- OpLine
- OpQuad
- OpCubic
- OpFillColor
- OpLineWidth
- OpTransform
- OpBeginClip
- OpEndClip
- OpFillImage
- OpSetFillMode
- OpGap
- )
- // FillModes, from setup.h.
- type FillMode uint32
- const (
- FillModeNonzero = 0
- FillModeStroke = 1
- )
- const CommandSize = int(unsafe.Sizeof(Command{}))
- const sceneElemSize = 36
- func (c Command) Op() Op {
- return Op(c[0])
- }
- func (c Command) String() string {
- switch Op(c[0]) {
- case OpNop:
- return "nop"
- case OpLine:
- from, to := DecodeLine(c)
- return fmt.Sprintf("line(%v, %v)", from, to)
- case OpGap:
- from, to := DecodeLine(c)
- return fmt.Sprintf("gap(%v, %v)", from, to)
- case OpQuad:
- from, ctrl, to := DecodeQuad(c)
- return fmt.Sprintf("quad(%v, %v, %v)", from, ctrl, to)
- case OpCubic:
- from, ctrl0, ctrl1, to := DecodeCubic(c)
- return fmt.Sprintf("cubic(%v, %v, %v, %v)", from, ctrl0, ctrl1, to)
- case OpFillColor:
- return fmt.Sprintf("fillcolor %#.8x", c[1])
- case OpLineWidth:
- return "linewidth"
- case OpTransform:
- t := f32.NewAffine2D(
- math.Float32frombits(c[1]),
- math.Float32frombits(c[3]),
- math.Float32frombits(c[5]),
- math.Float32frombits(c[2]),
- math.Float32frombits(c[4]),
- math.Float32frombits(c[6]),
- )
- return fmt.Sprintf("transform (%v)", t)
- case OpBeginClip:
- bounds := f32.Rectangle{
- Min: f32.Pt(math.Float32frombits(c[1]), math.Float32frombits(c[2])),
- Max: f32.Pt(math.Float32frombits(c[3]), math.Float32frombits(c[4])),
- }
- return fmt.Sprintf("beginclip (%v)", bounds)
- case OpEndClip:
- bounds := f32.Rectangle{
- Min: f32.Pt(math.Float32frombits(c[1]), math.Float32frombits(c[2])),
- Max: f32.Pt(math.Float32frombits(c[3]), math.Float32frombits(c[4])),
- }
- return fmt.Sprintf("endclip (%v)", bounds)
- case OpFillImage:
- return "fillimage"
- case OpSetFillMode:
- return "setfillmode"
- default:
- panic("unreachable")
- }
- }
- func Line(start, end f32.Point) Command {
- return Command{
- 0: uint32(OpLine),
- 1: math.Float32bits(start.X),
- 2: math.Float32bits(start.Y),
- 3: math.Float32bits(end.X),
- 4: math.Float32bits(end.Y),
- }
- }
- func Gap(start, end f32.Point) Command {
- return Command{
- 0: uint32(OpGap),
- 1: math.Float32bits(start.X),
- 2: math.Float32bits(start.Y),
- 3: math.Float32bits(end.X),
- 4: math.Float32bits(end.Y),
- }
- }
- func Cubic(start, ctrl0, ctrl1, end f32.Point) Command {
- return Command{
- 0: uint32(OpCubic),
- 1: math.Float32bits(start.X),
- 2: math.Float32bits(start.Y),
- 3: math.Float32bits(ctrl0.X),
- 4: math.Float32bits(ctrl0.Y),
- 5: math.Float32bits(ctrl1.X),
- 6: math.Float32bits(ctrl1.Y),
- 7: math.Float32bits(end.X),
- 8: math.Float32bits(end.Y),
- }
- }
- func Quad(start, ctrl, end f32.Point) Command {
- return Command{
- 0: uint32(OpQuad),
- 1: math.Float32bits(start.X),
- 2: math.Float32bits(start.Y),
- 3: math.Float32bits(ctrl.X),
- 4: math.Float32bits(ctrl.Y),
- 5: math.Float32bits(end.X),
- 6: math.Float32bits(end.Y),
- }
- }
- func Transform(m f32.Affine2D) Command {
- sx, hx, ox, hy, sy, oy := m.Elems()
- return Command{
- 0: uint32(OpTransform),
- 1: math.Float32bits(sx),
- 2: math.Float32bits(hy),
- 3: math.Float32bits(hx),
- 4: math.Float32bits(sy),
- 5: math.Float32bits(ox),
- 6: math.Float32bits(oy),
- }
- }
- func SetLineWidth(width float32) Command {
- return Command{
- 0: uint32(OpLineWidth),
- 1: math.Float32bits(width),
- }
- }
- func BeginClip(bbox f32.Rectangle) Command {
- return Command{
- 0: uint32(OpBeginClip),
- 1: math.Float32bits(bbox.Min.X),
- 2: math.Float32bits(bbox.Min.Y),
- 3: math.Float32bits(bbox.Max.X),
- 4: math.Float32bits(bbox.Max.Y),
- }
- }
- func EndClip(bbox f32.Rectangle) Command {
- return Command{
- 0: uint32(OpEndClip),
- 1: math.Float32bits(bbox.Min.X),
- 2: math.Float32bits(bbox.Min.Y),
- 3: math.Float32bits(bbox.Max.X),
- 4: math.Float32bits(bbox.Max.Y),
- }
- }
- func FillColor(col color.RGBA) Command {
- return Command{
- 0: uint32(OpFillColor),
- 1: uint32(col.R)<<24 | uint32(col.G)<<16 | uint32(col.B)<<8 | uint32(col.A),
- }
- }
- func FillImage(index int, offset image.Point) Command {
- x := int16(offset.X)
- y := int16(offset.Y)
- return Command{
- 0: uint32(OpFillImage),
- 1: uint32(index),
- 2: uint32(uint16(x)) | uint32(uint16(y))<<16,
- }
- }
- func SetFillMode(mode FillMode) Command {
- return Command{
- 0: uint32(OpSetFillMode),
- 1: uint32(mode),
- }
- }
- func DecodeLine(cmd Command) (from, to f32.Point) {
- if cmd[0] != uint32(OpLine) {
- panic("invalid command")
- }
- from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
- to = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
- return
- }
- func DecodeGap(cmd Command) (from, to f32.Point) {
- if cmd[0] != uint32(OpGap) {
- panic("invalid command")
- }
- from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
- to = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
- return
- }
- func DecodeQuad(cmd Command) (from, ctrl, to f32.Point) {
- if cmd[0] != uint32(OpQuad) {
- panic("invalid command")
- }
- from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
- ctrl = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
- to = f32.Pt(math.Float32frombits(cmd[5]), math.Float32frombits(cmd[6]))
- return
- }
- func DecodeCubic(cmd Command) (from, ctrl0, ctrl1, to f32.Point) {
- if cmd[0] != uint32(OpCubic) {
- panic("invalid command")
- }
- from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
- ctrl0 = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
- ctrl1 = f32.Pt(math.Float32frombits(cmd[5]), math.Float32frombits(cmd[6]))
- to = f32.Pt(math.Float32frombits(cmd[7]), math.Float32frombits(cmd[8]))
- return
- }
|