shiny/iconvg: make the zero Encoder value usable.
Change-Id: Iee4b4be38ef43dab1475bf5cebdb678b08f8c29a
Reviewed-on: https://go-review.googlesource.com/29890
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/shiny/iconvg/encode.go b/shiny/iconvg/encode.go
index 4c0d950..9d5fe45 100644
--- a/shiny/iconvg/encode.go
+++ b/shiny/iconvg/encode.go
@@ -16,18 +16,19 @@
errStylingOpsUsedInDrawingMode = errors.New("iconvg: styling ops used in drawing mode")
)
-// TODO: delete the NewEncoder function, and just make the zero value usable.
+type mode uint8
-// NewEncoder returns a new Encoder for the given Metadata.
-func NewEncoder(m Metadata) *Encoder {
- e := &Encoder{
- buf: make(buffer, 0, 1024),
- }
- e.Reset(m)
- return e
-}
+const (
+ modeInitial mode = iota
+ modeStyling
+ modeDrawing
+)
// Encoder is an IconVG encoder.
+//
+// The zero value is usable. Calling Reset, which is optional, sets the
+// Metadata for the subsequent encoded form. If Reset is not called before
+// other Encoder methods, the default metadata is implied.
type Encoder struct {
buf buffer
altBuf buffer
@@ -49,6 +50,9 @@
if e.err != nil {
return nil, e.err
}
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ }
return []byte(e.buf), nil
}
@@ -57,6 +61,7 @@
*e = Encoder{
buf: append(e.buf[:0], magic...),
metadata: m,
+ mode: modeStyling,
lod1: positiveInfinity,
}
@@ -88,17 +93,44 @@
}
}
-func (e *Encoder) CSel() uint32 { return e.cSel }
-func (e *Encoder) NSel() uint32 { return e.nSel }
-func (e *Encoder) LOD() (lod0, lod1 float32) { return e.lod0, e.lod1 }
+func (e *Encoder) appendDefaultMetadata() {
+ e.buf = append(e.buf[:0], magic...)
+ e.buf = append(e.buf, 0x00) // There are zero metadata chunks.
+ e.mode = modeStyling
+}
+
+func (e *Encoder) CSel() uint32 {
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ }
+ return e.cSel
+}
+
+func (e *Encoder) NSel() uint32 {
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ }
+ return e.nSel
+}
+
+func (e *Encoder) LOD() (lod0, lod1 float32) {
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ }
+ return e.lod0, e.lod1
+}
func (e *Encoder) SetCSel(cSel uint32) {
if e.err != nil {
return
}
if e.mode != modeStyling {
- e.err = errStylingOpsUsedInDrawingMode
- return
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ } else {
+ e.err = errStylingOpsUsedInDrawingMode
+ return
+ }
}
e.cSel = cSel
e.buf = append(e.buf, uint8(cSel&0x3f))
@@ -109,8 +141,12 @@
return
}
if e.mode != modeStyling {
- e.err = errStylingOpsUsedInDrawingMode
- return
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ } else {
+ e.err = errStylingOpsUsedInDrawingMode
+ return
+ }
}
e.nSel = nSel
e.buf = append(e.buf, uint8((nSel&0x3f)|0x40))
@@ -121,8 +157,12 @@
return
}
if e.mode != modeStyling {
- e.err = errStylingOpsUsedInDrawingMode
- return
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ } else {
+ e.err = errStylingOpsUsedInDrawingMode
+ return
+ }
}
e.lod0 = lod0
e.lod1 = lod1
@@ -136,8 +176,12 @@
return
}
if e.mode != modeStyling {
- e.err = errStylingOpsUsedInDrawingMode
- return
+ if e.mode == modeInitial {
+ e.appendDefaultMetadata()
+ } else {
+ e.err = errStylingOpsUsedInDrawingMode
+ return
+ }
}
if adj < 0 || 6 < adj {
e.err = errInvalidSelectorAdjustment
diff --git a/shiny/iconvg/encode_test.go b/shiny/iconvg/encode_test.go
index 82a096e..6c42c5e 100644
--- a/shiny/iconvg/encode_test.go
+++ b/shiny/iconvg/encode_test.go
@@ -11,6 +11,21 @@
"golang.org/x/image/math/f32"
)
+func TestEncoderZeroValue(t *testing.T) {
+ var e Encoder
+ got, err := e.Bytes()
+ if err != nil {
+ t.Fatalf("Bytes: %v", err)
+ }
+ want := []byte{
+ 0x89, 0x49, 0x56, 0x47, // Magic identifier.
+ 0x00, // Zero metadata chunks.
+ }
+ if !bytes.Equal(got, want) {
+ t.Errorf("\ngot %d bytes:\n% x\nwant %d bytes:\n% x", len(got), got, len(want), want)
+ }
+}
+
// actionInfoIconVG is the IconVG encoding of the "action/info" icon from the
// Material Design icon set.
//
@@ -24,7 +39,8 @@
}
func TestEncodeActionInfo(t *testing.T) {
- e := NewEncoder(Metadata{
+ var e Encoder
+ e.Reset(Metadata{
ViewBox: Rectangle{
Min: f32.Vec2{-24, -24},
Max: f32.Vec2{+24, +24},
diff --git a/shiny/iconvg/iconvg.go b/shiny/iconvg/iconvg.go
index ec5a881..75e78cc 100644
--- a/shiny/iconvg/iconvg.go
+++ b/shiny/iconvg/iconvg.go
@@ -26,13 +26,6 @@
midSuggestedPalette = 1
)
-type mode bool
-
-const (
- modeStyling mode = false
- modeDrawing mode = true
-)
-
// Rectangle is defined by its minimum and maximum coordinates.
type Rectangle struct {
Min, Max f32.Vec2