swf-go/subtypes/SHAPE.go

336 lines
7.6 KiB
Go

package subtypes
import (
"git.gammaspectra.live/WeebDataHoarder/swf-go/types"
"reflect"
)
type SHAPE struct {
_ struct{} `swfFlags:"root"`
FillBits uint8 `swfBits:",4"`
LineBits uint8 `swfBits:",4"`
Records SHAPERECORDS
}
type SHAPEWITHSTYLE struct {
_ struct{} `swfFlags:"root"`
FillStyles FILLSTYLEARRAY
LineStyles LINESTYLEARRAY
FillBits uint8 `swfBits:",4"`
LineBits uint8 `swfBits:",4"`
Records SHAPERECORDS
}
type SHAPERECORDS []SHAPERECORD
func (records *SHAPERECORDS) SWFRead(r types.DataReader, ctx types.ReaderContext) (err error) {
fillBits := uint8(ctx.GetNestedType("FillBits").Uint())
lineBits := uint8(ctx.GetNestedType("LineBits").Uint())
*records = make(SHAPERECORDS, 0, 512)
for {
isEdge, err := types.ReadBool(r)
if err != nil {
return err
}
if !isEdge {
rec := StyleChangeRecord{}
rec.FillBits = fillBits
rec.LineBits = lineBits
err = rec.SWFRead(r, types.ReaderContext{
Version: ctx.Version,
Root: reflect.ValueOf(rec),
Flags: ctx.Flags,
})
if err != nil {
return err
}
if rec.IsEnd() {
//end record
*records = append(*records, &EndShapeRecord{})
break
}
//store new value
fillBits = rec.FillBits
lineBits = rec.LineBits
*records = append(*records, &rec)
} else {
isStraight, err := types.ReadBool(r)
if err != nil {
return err
}
if isStraight {
rec := StraightEdgeRecord{}
err = rec.SWFRead(r, types.ReaderContext{
Version: ctx.Version,
Root: reflect.ValueOf(rec),
Flags: ctx.Flags,
})
if err != nil {
return err
}
*records = append(*records, &rec)
} else {
rec := CurvedEdgeRecord{}
err = rec.SWFRead(r, types.ReaderContext{
Version: ctx.Version,
Root: reflect.ValueOf(rec),
Flags: ctx.Flags,
})
if err != nil {
return err
}
*records = append(*records, &rec)
}
}
}
r.Align()
return nil
}
type EndShapeRecord struct {
}
func (s *EndShapeRecord) RecordType() RecordType {
return RecordTypeEndShape
}
type StyleChangeRecord struct {
_ struct{} `swfFlags:"root"`
Flag struct {
NewStyles bool
LineStyle bool
FillStyle1 bool
FillStyle0 bool
MoveTo bool
}
MoveBits uint8 `swfBits:",5" swfCondition:"Flag.MoveTo"`
MoveDeltaX, MoveDeltaY types.Twip `swfBits:"MoveBits,signed" swfCondition:"Flag.MoveTo"`
FillStyle0 uint16 `swfBits:"FillBits" swfCondition:"Flag.FillStyle0"`
FillStyle1 uint16 `swfBits:"FillBits" swfCondition:"Flag.FillStyle1"`
LineStyle uint16 `swfBits:"LineBits" swfCondition:"Flag.LineStyle"`
FillStyles FILLSTYLEARRAY `swfFlags:"align" swfCondition:"Flag.NewStyles"`
LineStyles LINESTYLEARRAY `swfCondition:"Flag.NewStyles"`
FillBits uint8 `swfBits:",4" swfCondition:"Flag.NewStyles"`
LineBits uint8 `swfBits:",4" swfCondition:"Flag.NewStyles"`
}
func (rec *StyleChangeRecord) IsEnd() bool {
return !rec.Flag.NewStyles && !rec.Flag.LineStyle && !rec.Flag.FillStyle1 && !rec.Flag.FillStyle0 && !rec.Flag.MoveTo
}
func (rec *StyleChangeRecord) SWFRead(r types.DataReader, ctx types.ReaderContext) (err error) {
//this is not necessary, but speedups read massively
rec.Flag.NewStyles, err = types.ReadBool(r)
if err != nil {
return err
}
rec.Flag.LineStyle, err = types.ReadBool(r)
if err != nil {
return err
}
rec.Flag.FillStyle1, err = types.ReadBool(r)
if err != nil {
return err
}
rec.Flag.FillStyle0, err = types.ReadBool(r)
if err != nil {
return err
}
rec.Flag.MoveTo, err = types.ReadBool(r)
if err != nil {
return err
}
if rec.Flag.MoveTo {
rec.MoveBits, err = types.ReadUB[uint8](r, 5)
if err != nil {
return err
}
rec.MoveDeltaX, err = types.ReadSB[types.Twip](r, uint64(rec.MoveBits))
if err != nil {
return err
}
rec.MoveDeltaY, err = types.ReadSB[types.Twip](r, uint64(rec.MoveBits))
if err != nil {
return err
}
}
if rec.Flag.FillStyle0 {
rec.FillStyle0, err = types.ReadUB[uint16](r, uint64(rec.FillBits))
if err != nil {
return err
}
}
if rec.Flag.FillStyle1 {
rec.FillStyle1, err = types.ReadUB[uint16](r, uint64(rec.FillBits))
if err != nil {
return err
}
}
if rec.Flag.LineStyle {
rec.LineStyle, err = types.ReadUB[uint16](r, uint64(rec.LineBits))
if err != nil {
return err
}
}
if rec.Flag.NewStyles {
r.Align()
err = types.ReadType(r, types.ReaderContext{
Version: ctx.Version,
Root: reflect.ValueOf(rec.FillStyles),
Flags: ctx.Flags,
}, &rec.FillStyles)
if err != nil {
return err
}
err = types.ReadType(r, types.ReaderContext{
Version: ctx.Version,
Root: reflect.ValueOf(rec.LineStyles),
Flags: ctx.Flags,
}, &rec.LineStyles)
if err != nil {
return err
}
rec.FillBits, err = types.ReadUB[uint8](r, 4)
if err != nil {
return err
}
rec.LineBits, err = types.ReadUB[uint8](r, 4)
if err != nil {
return err
}
}
return nil
}
func (rec *StyleChangeRecord) RecordType() RecordType {
return RecordTypeStyleChange
}
type StraightEdgeRecord struct {
_ struct{} `swfFlags:"root"`
NumBits uint8 `swfBits:",4"`
GeneralLine bool
VertLine bool `swfCondition:"HasVertLine()"`
DeltaX types.Twip `swfBits:"NumBits+2,signed" swfCondition:"HasDeltaX()"`
DeltaY types.Twip `swfBits:"NumBits+2,signed" swfCondition:"HasDeltaY()"`
}
func (s *StraightEdgeRecord) SWFRead(r types.DataReader, ctx types.ReaderContext) (err error) {
//this is not necessary, but speedups read massively
s.NumBits, err = types.ReadUB[uint8](r, 4)
if err != nil {
return err
}
s.GeneralLine, err = types.ReadBool(r)
if err != nil {
return err
}
if s.HasVertLine(ctx) {
s.VertLine, err = types.ReadBool(r)
if err != nil {
return err
}
}
if s.HasDeltaX(ctx) {
s.DeltaX, err = types.ReadSB[types.Twip](r, uint64(s.NumBits+2))
if err != nil {
return err
}
}
if s.HasDeltaY(ctx) {
s.DeltaY, err = types.ReadSB[types.Twip](r, uint64(s.NumBits+2))
if err != nil {
return err
}
}
return nil
}
func (s *StraightEdgeRecord) HasVertLine(ctx types.ReaderContext) bool {
return !s.GeneralLine
}
func (s *StraightEdgeRecord) HasDeltaX(ctx types.ReaderContext) bool {
return s.GeneralLine || !s.VertLine
}
func (s *StraightEdgeRecord) HasDeltaY(ctx types.ReaderContext) bool {
return s.GeneralLine || s.VertLine
}
func (s *StraightEdgeRecord) RecordType() RecordType {
return RecordTypeStraightEdge
}
type CurvedEdgeRecord struct {
_ struct{} `swfFlags:"root"`
NumBits uint8 `swfBits:",4"`
ControlDeltaX, ControlDeltaY types.Twip `swfBits:"NumBits+2,signed"`
AnchorDeltaX, AnchorDeltaY types.Twip `swfBits:"NumBits+2,signed"`
}
func (s *CurvedEdgeRecord) SWFRead(r types.DataReader, ctx types.ReaderContext) (err error) {
//this is not necessary, but speedups read massively
s.NumBits, err = types.ReadUB[uint8](r, 4)
if err != nil {
return err
}
s.ControlDeltaX, err = types.ReadSB[types.Twip](r, uint64(s.NumBits+2))
if err != nil {
return err
}
s.ControlDeltaY, err = types.ReadSB[types.Twip](r, uint64(s.NumBits+2))
if err != nil {
return err
}
s.AnchorDeltaX, err = types.ReadSB[types.Twip](r, uint64(s.NumBits+2))
if err != nil {
return err
}
s.AnchorDeltaY, err = types.ReadSB[types.Twip](r, uint64(s.NumBits+2))
if err != nil {
return err
}
return nil
}
func (s *CurvedEdgeRecord) RecordType() RecordType {
return RecordTypeCurvedEdge
}
type RecordType uint8
const (
RecordTypeEndShape = RecordType(iota)
RecordTypeStyleChange
RecordTypeStraightEdge
RecordTypeCurvedEdge
)
type SHAPERECORD interface {
RecordType() RecordType
}