336 lines
7.6 KiB
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
|
|
}
|