swf2ass-go/types/shapes/ClipPath.go

106 lines
2.2 KiB
Go

package shapes
import (
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
"github.com/ctessum/polyclip-go"
"slices"
)
type ClipPath struct {
Clip ComplexPolygon
}
func NewClipPath(shape Shape) *ClipPath {
return &ClipPath{
Clip: ComplexPolygon{
Pol: NewPolygonFromShape(shape),
},
}
}
func (c *ClipPath) AddShape(shape Shape) {
c.Clip = c.Clip.Merge(ComplexPolygon{Pol: NewPolygonFromShape(shape)})
}
func (c *ClipPath) GetShape() Shape {
return c.Clip.GetShape()
}
func (c *ClipPath) ApplyMatrixTransform(transform math.MatrixTransform, applyTranslation bool) *ClipPath {
pol := make(polyclip.Polygon, len(c.Clip.Pol))
for i, contour := range c.Clip.Pol {
pol[i] = make(polyclip.Contour, len(contour))
for j, p := range contour {
out := transform.ApplyToVector(math.NewVector2(p.X, p.Y), applyTranslation)
pol[i][j] = polyclip.Point{
X: out.X,
Y: out.Y,
}
}
}
return &ClipPath{
Clip: ComplexPolygon{
Pol: pol,
},
}
}
func (c *ClipPath) Merge(o *ClipPath) *ClipPath {
return &ClipPath{
Clip: c.Clip.Merge(o.Clip),
}
}
// ClipShape Clips a shape, but attempts to recover original curved records
func (c *ClipPath) ClipShape(o Shape, recover bool) (r Shape) {
if !recover {
return c.Clip.Intersect(ComplexPolygon{
Pol: NewPolygonFromShape(o),
}).GetShape()
}
flatShape, correspondence := o.FlattenWithCorrespondence()
outShape := ComplexPolygon{
Pol: NewPolygonFromShape(flatShape),
}.Intersect(c.Clip).GetShape()
for i := 0; i < len(outShape); i++ {
var found bool
for j, e := range correspondence {
if func() bool {
k, l := i, 0
for {
if l >= len(e.Flattened) {
return true
}
if k >= len(outShape) {
return false
}
if !e.Flattened[l].Equals(outShape[k]) {
return false
}
k++
l++
}
}() {
//They are the same! Append entry back
i += len(e.Flattened) - 1
r = append(r, e.Original)
slices.Delete(correspondence, j, j+1)
found = true
break
}
}
if !found {
r = append(r, outShape[i])
}
}
return r
}
func (c *ClipPath) Intersect(o *ClipPath) *ClipPath {
return &ClipPath{
Clip: c.Clip.Intersect(o.Clip),
}
}