op: change Defer to only restore transformation state

It turns out restoring all operation state from the moment Defer
is executed is too much; for example, a right-click pop-up needs
the transformation, but not the current clip.

Change Defer to only restore the transformation, and reset all
other state.

Other combinations may be needed in future; we'll deal with them then,
possibly by exposing the load state mask.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-01-19 20:04:30 +01:00
parent eea1dbc176
commit d6886737a5
8 changed files with 84 additions and 34 deletions
+15 -1
View File
@@ -57,7 +57,7 @@ const (
TypeKeyFocusLen = 1 + 1
TypeKeySoftKeyboardLen = 1 + 1
TypeSaveLen = 1 + 4
TypeLoadLen = 1 + 4
TypeLoadLen = 1 + 1 + 4
TypeAuxLen = 1
TypeClipLen = 1 + 4*4 + 1
TypeProfileLen = 1
@@ -67,6 +67,20 @@ const (
TypeDashLen = 1 + 4 + 1
)
// StateMask is a bitmask of state types a load operation
// should restore.
type StateMask uint8
const (
TransformState StateMask = 1 << iota
AllState = ^StateMask(0)
)
// InitialStateID is the ID for saving and loading
// the initial operation state.
const InitialStateID = 0
func (t OpType) Size() int {
return [...]int{
TypeMacroLen,
+3 -3
View File
@@ -72,11 +72,11 @@ func DecodeSave(data []byte) int {
return int(bo.Uint32(data[1:]))
}
// DecodeLoad decodes the state id of a restore op.
func DecodeLoad(data []byte) int {
// DecodeLoad decodes the state id and mask of a load op.
func DecodeLoad(data []byte) (int, opconst.StateMask) {
if opconst.OpType(data[0]) != opconst.TypeLoad {
panic("invalid op")
}
bo := binary.LittleEndian
return int(bo.Uint32(data[1:]))
return int(bo.Uint32(data[2:])), opconst.StateMask(data[1])
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 420 B

+7 -3
View File
@@ -107,13 +107,17 @@ func TestDeferredPaint(t *testing.T) {
run(t, func(o *op.Ops) {
state := op.Save(o)
clip.Rect(image.Rect(0, 0, 80, 80)).Op().Add(o)
paint.ColorOp{Color: color.NRGBA{A: 0xff, R: 0xff}}.Add(o)
paint.ColorOp{Color: color.NRGBA{A: 0xff, G: 0xff}}.Add(o)
paint.PaintOp{}.Add(o)
op.Affine(f32.Affine2D{}.Offset(f32.Pt(20, 20))).Add(o)
m := op.Record(o)
clip.Rect(image.Rect(0, 0, 80, 80)).Op().Add(o)
paint.ColorOp{Color: color.NRGBA{A: 0xff, R: 0xff, G: 0xff}}.Add(o)
paint.PaintOp{}.Add(o)
paintMacro := m.Stop()
op.Defer(o, paintMacro)
paint.ColorOp{Color: color.NRGBA{A: 0xff, G: 0xff}}.Add(o)
paint.PaintOp{}.Add(o)
state.Load()
op.Affine(f32.Affine2D{}.Offset(f32.Pt(10, 10))).Add(o)
clip.Rect(image.Rect(0, 0, 80, 80)).Op().Add(o)