Better stroke width based on matrix?
This commit is contained in:
parent
116c3b5b56
commit
6ab2e3ddae
|
@ -37,8 +37,8 @@ func NewRenderer(frameRate float64, display shapes.Rectangle[float64]) *Renderer
|
|||
"; https://git.gammaspectra.live/WeebDataHoarder/swf2ass-go",
|
||||
"Title: swf2ass",
|
||||
"ScriptType: v4.00+",
|
||||
"; TODO: maybe set WrapStyle: 2",
|
||||
"WrapStyle: 0",
|
||||
//TODO: WrapStyle: 0 or 2?
|
||||
"WrapStyle: 2",
|
||||
"ScaledBorderAndShadow: yes",
|
||||
"YCbCr Matrix: PC.709",
|
||||
fmt.Sprintf("PlayResX: %d", width),
|
||||
|
|
|
@ -3,6 +3,7 @@ package tag
|
|||
import (
|
||||
"fmt"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/ass/time"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/shapes"
|
||||
)
|
||||
|
||||
|
@ -10,7 +11,7 @@ type BlurGaussianTag struct {
|
|||
Blur float64
|
||||
}
|
||||
|
||||
func (t *BlurGaussianTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *BlurGaussianTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
if lineStyleRecord, ok := record.(*shapes.LineStyleRecord); ok {
|
||||
t.Blur = lineStyleRecord.Blur
|
||||
} else if fillStyleRecord, ok := record.(*shapes.FillStyleRecord); ok {
|
||||
|
@ -21,9 +22,9 @@ func (t *BlurGaussianTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
|||
return t
|
||||
}
|
||||
|
||||
func (t *BlurGaussianTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
func (t *BlurGaussianTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
t2 := &BlurGaussianTag{}
|
||||
t2.FromStyleRecord(record)
|
||||
t2.FromStyleRecord(record, transform)
|
||||
return t2
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package tag
|
|||
import (
|
||||
"fmt"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/ass/time"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/shapes"
|
||||
)
|
||||
|
||||
|
@ -10,7 +11,7 @@ type BlurTag struct {
|
|||
Blur int64
|
||||
}
|
||||
|
||||
func (t *BlurTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *BlurTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
if lineStyleRecord, ok := record.(*shapes.LineStyleRecord); ok {
|
||||
t.Blur = int64(lineStyleRecord.Blur)
|
||||
} else if fillStyleRecord, ok := record.(*shapes.FillStyleRecord); ok {
|
||||
|
@ -21,9 +22,9 @@ func (t *BlurTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
|||
return t
|
||||
}
|
||||
|
||||
func (t *BlurTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
func (t *BlurTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
t2 := &BlurTag{}
|
||||
t2.FromStyleRecord(record)
|
||||
t2.FromStyleRecord(record, transform)
|
||||
return t2
|
||||
}
|
||||
|
||||
|
|
|
@ -5,26 +5,29 @@ import (
|
|||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/ass/time"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/shapes"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type BorderTag struct {
|
||||
Size math.Vector2[float64]
|
||||
}
|
||||
|
||||
func (t *BorderTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *BorderTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
if lineStyleRecord, ok := record.(*shapes.LineStyleRecord); ok {
|
||||
t.Size = math.NewVector2(lineStyleRecord.Width, lineStyleRecord.Width)
|
||||
w := lineStyleRecord.StrokeWidth(transform)
|
||||
t.Size = math.NewVector2(w, w)
|
||||
} else if fillStyleRecord, ok := record.(*shapes.FillStyleRecord); ok && fillStyleRecord.Border != nil {
|
||||
t.Size = math.NewVector2(fillStyleRecord.Border.Width, fillStyleRecord.Border.Width)
|
||||
w := fillStyleRecord.Border.StrokeWidth(transform)
|
||||
t.Size = math.NewVector2(w, w)
|
||||
} else {
|
||||
t.Size = math.NewVector2[float64](0, 0)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *BorderTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
func (t *BorderTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
t2 := &BorderTag{}
|
||||
t2.FromStyleRecord(record)
|
||||
t2.FromStyleRecord(record, transform)
|
||||
return t2
|
||||
}
|
||||
|
||||
|
@ -40,8 +43,8 @@ func (t *BorderTag) Encode(event time.EventTime) string {
|
|||
if t.Size.X == 0 {
|
||||
return "\\bord0"
|
||||
}
|
||||
return fmt.Sprintf("\\bord%.02F", t.Size.X)
|
||||
return fmt.Sprintf("\\bord%s", strconv.FormatFloat(t.Size.X, 'f', -1, 64))
|
||||
} else {
|
||||
return fmt.Sprintf("\\xbord%.02F\\ybord%.02F", t.Size.X, t.Size.Y)
|
||||
return fmt.Sprintf("\\xbord%s\\ybord%s", strconv.FormatFloat(t.Size.X, 'f', -1, 64), strconv.FormatFloat(t.Size.Y, 'f', -1, 64))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,14 +69,14 @@ func (t *ContainerTag) TransitionMatrixTransform(event Event, transform math.Mat
|
|||
return container
|
||||
}
|
||||
|
||||
func (t *ContainerTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
func (t *ContainerTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
container := t.Clone(false)
|
||||
|
||||
index := event.GetEnd() - event.GetStart()
|
||||
|
||||
for _, tag := range container.Tags {
|
||||
if colorTag, ok := tag.(StyleTag); ok {
|
||||
newTag := colorTag.TransitionStyleRecord(event, record)
|
||||
newTag := colorTag.TransitionStyleRecord(event, record, transform)
|
||||
if newTag == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ func (t *ContainerTag) FromMatrixTransform(transform math.MatrixTransform) Posit
|
|||
panic("not supported")
|
||||
}
|
||||
|
||||
func (t *ContainerTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *ContainerTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
panic("not supported")
|
||||
}
|
||||
|
||||
|
@ -293,36 +293,31 @@ func ContainerTagFromPathEntry(path shapes.DrawPath, clip *shapes.ClipPath, colo
|
|||
return nil
|
||||
}
|
||||
|
||||
container.TryAppend((&BorderTag{}).FromStyleRecord(path.Style))
|
||||
if bakeMatrixTransforms {
|
||||
container.BakeTransforms = &matrixTransform
|
||||
container.TryAppend((&PositionTag{}).FromMatrixTransform(matrixTransform))
|
||||
} else {
|
||||
container.TryAppend((&PositionTag{}).FromMatrixTransform(matrixTransform))
|
||||
container.TryAppend((&MatrixTransformTag{}).FromMatrixTransform(matrixTransform))
|
||||
}
|
||||
|
||||
container.TryAppend((&BlurGaussianTag{}).FromStyleRecord(path.Style))
|
||||
container.TryAppend((&BorderTag{}).FromStyleRecord(path.Style, matrixTransform))
|
||||
|
||||
container.TryAppend((&BlurGaussianTag{}).FromStyleRecord(path.Style, matrixTransform))
|
||||
|
||||
{
|
||||
lineColorTag := &LineColorTag{}
|
||||
lineColorTag.FromStyleRecord(path.Style)
|
||||
lineColorTag.FromStyleRecord(path.Style, matrixTransform)
|
||||
container.TryAppend(lineColorTag.ApplyColorTransform(colorTransform))
|
||||
}
|
||||
|
||||
{
|
||||
fillColorTag := &FillColorTag{}
|
||||
fillColorTag.FromStyleRecord(path.Style)
|
||||
fillColorTag.FromStyleRecord(path.Style, matrixTransform)
|
||||
container.TryAppend(fillColorTag.ApplyColorTransform(colorTransform))
|
||||
}
|
||||
|
||||
if bakeMatrixTransforms {
|
||||
container.BakeTransforms = &matrixTransform
|
||||
|
||||
container.TryAppend((&PositionTag{}).FromMatrixTransform(matrixTransform))
|
||||
|
||||
drawTag := DrawingTag(NewDrawTag(path.Commands, settings.GlobalSettings.ASSDrawingScale))
|
||||
|
||||
container.TryAppend(drawTag)
|
||||
} else {
|
||||
container.TryAppend((&PositionTag{}).FromMatrixTransform(matrixTransform))
|
||||
container.TryAppend((&MatrixTransformTag{}).FromMatrixTransform(matrixTransform))
|
||||
|
||||
container.TryAppend(NewDrawTag(path.Commands, settings.GlobalSettings.ASSDrawingScale))
|
||||
}
|
||||
container.TryAppend(NewDrawTag(path.Commands, settings.GlobalSettings.ASSDrawingScale))
|
||||
|
||||
return container
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ type FillColorTag struct {
|
|||
OriginalColor *math.Color
|
||||
}
|
||||
|
||||
func (t *FillColorTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *FillColorTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
if fillStyleRecord, ok := record.(*shapes.FillStyleRecord); ok {
|
||||
if color, ok := fillStyleRecord.Fill.(math.Color); ok {
|
||||
t.Color = &color
|
||||
|
@ -27,9 +27,9 @@ func (t *FillColorTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
|||
return t
|
||||
}
|
||||
|
||||
func (t *FillColorTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
t2 := &LineColorTag{}
|
||||
t2.FromStyleRecord(record)
|
||||
func (t *FillColorTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
t2 := &FillColorTag{}
|
||||
t2.FromStyleRecord(record, transform)
|
||||
return t2
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ type LineColorTag struct {
|
|||
OriginalColor *math.Color
|
||||
}
|
||||
|
||||
func (t *LineColorTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *LineColorTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
if lineStyleRecord, ok := record.(*shapes.LineStyleRecord); ok {
|
||||
t.Color = &lineStyleRecord.Color
|
||||
t.OriginalColor = &lineStyleRecord.Color
|
||||
|
@ -26,9 +26,9 @@ func (t *LineColorTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
|||
return t
|
||||
}
|
||||
|
||||
func (t *LineColorTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
func (t *LineColorTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
t2 := &LineColorTag{}
|
||||
t2.FromStyleRecord(record)
|
||||
t2.FromStyleRecord(record, transform)
|
||||
return t2
|
||||
}
|
||||
|
||||
|
|
|
@ -90,10 +90,10 @@ func (t *PositionTag) Encode(event time.EventTime) string {
|
|||
start = event.GetDurationFromStartOffset(t.Start).Milliseconds() - 1
|
||||
end = event.GetDurationFromStartOffset(t.Start).Milliseconds()
|
||||
}
|
||||
return fmt.Sprintf("\\move(%s,%s,%s,%s,%d,%d)", strconv.FormatFloat(t.From.X, 'f', 0, 64), strconv.FormatFloat(t.From.Y, 'f', 0, 64), strconv.FormatFloat(t.To.X, 'f', 0, 64), strconv.FormatFloat(t.To.Y, 'f', 0, 64), start, end)
|
||||
return fmt.Sprintf("\\move(%s,%s,%s,%s,%d,%d)", strconv.FormatFloat(t.From.X, 'f', -1, 64), strconv.FormatFloat(t.From.Y, 'f', -1, 64), strconv.FormatFloat(t.To.X, 'f', -1, 64), strconv.FormatFloat(t.To.Y, 'f', -1, 64), start, end)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("\\pos(%s,%s)", strconv.FormatFloat(t.From.X, 'f', 0, 64), strconv.FormatFloat(t.From.Y, 'f', 0, 64))
|
||||
return fmt.Sprintf("\\pos(%s,%s)", strconv.FormatFloat(t.From.X, 'f', -1, 64), strconv.FormatFloat(t.From.Y, 'f', -1, 64))
|
||||
}
|
||||
|
||||
func (t *PositionTag) Equals(tag Tag) bool {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/ass/time"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ScaleTag struct {
|
||||
|
@ -16,7 +17,7 @@ func (t *ScaleTag) TransitionMatrixTransform(event Event, transform math.MatrixT
|
|||
|
||||
func (t *ScaleTag) Encode(event time.EventTime) string {
|
||||
//TODO: precision?
|
||||
return fmt.Sprintf("\\fscx%.5F\\fscy%.5F", t.Scale.X, t.Scale.Y)
|
||||
return fmt.Sprintf("\\fscx%s\\fscy%s", strconv.FormatFloat(t.Scale.X, 'f', -1, 64), strconv.FormatFloat(t.Scale.Y, 'f', -1, 64))
|
||||
}
|
||||
|
||||
func (t *ScaleTag) Equals(tag Tag) bool {
|
||||
|
|
|
@ -3,6 +3,7 @@ package tag
|
|||
import (
|
||||
"fmt"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/ass/time"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/shapes"
|
||||
)
|
||||
|
||||
|
@ -10,15 +11,15 @@ type ShadowTag struct {
|
|||
Depth float64
|
||||
}
|
||||
|
||||
func (t *ShadowTag) FromStyleRecord(record shapes.StyleRecord) StyleTag {
|
||||
func (t *ShadowTag) FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
//TODO?
|
||||
t.Depth = 0
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *ShadowTag) TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag {
|
||||
func (t *ShadowTag) TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag {
|
||||
t2 := &ShadowTag{}
|
||||
t2.FromStyleRecord(record)
|
||||
t2.FromStyleRecord(record, transform)
|
||||
return t2
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/ass/time"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ShearingTag struct {
|
||||
|
@ -16,7 +17,7 @@ func (t *ShearingTag) TransitionMatrixTransform(event Event, transform math.Matr
|
|||
|
||||
func (t *ShearingTag) Encode(event time.EventTime) string {
|
||||
//TODO: precision?
|
||||
return fmt.Sprintf("\\fax%.5F\\fay%.5F", t.Shear.X, t.Shear.Y)
|
||||
return fmt.Sprintf("\\fax%s\\fay%s", strconv.FormatFloat(t.Shear.X, 'f', -1, 64), strconv.FormatFloat(t.Shear.Y, 'f', -1, 64))
|
||||
}
|
||||
|
||||
func (t *ShearingTag) Equals(tag Tag) bool {
|
||||
|
|
|
@ -18,8 +18,8 @@ type Event interface {
|
|||
|
||||
type StyleTag interface {
|
||||
Tag
|
||||
TransitionStyleRecord(event Event, record shapes.StyleRecord) StyleTag
|
||||
FromStyleRecord(record shapes.StyleRecord) StyleTag
|
||||
TransitionStyleRecord(event Event, record shapes.StyleRecord, transform math.MatrixTransform) StyleTag
|
||||
FromStyleRecord(record shapes.StyleRecord, transform math.MatrixTransform) StyleTag
|
||||
}
|
||||
|
||||
type PositioningTag interface {
|
||||
|
|
|
@ -92,6 +92,7 @@ func (d *MorphShapeDefinition) GetShapeList(ratio float64) (list shapes.DrawPath
|
|||
list = append(list, shapes.DrawPathStroke(&shapes.LineStyleRecord{
|
||||
Width: math2.Lerp(c1LineStyle.Width, c2LineStyle.Width, ratio),
|
||||
Color: math2.LerpColor(c1LineStyle.Color, c2LineStyle.Color, ratio),
|
||||
//TODO: blur
|
||||
}, &shape, nil))
|
||||
} else {
|
||||
panic("unsupported")
|
||||
|
|
|
@ -120,6 +120,16 @@ func (m MatrixTransform) GetMatrix() mat.Matrix {
|
|||
return m.matrix
|
||||
}
|
||||
|
||||
// MinimumStrokeWidth
|
||||
// Given a matrix, calculates the scale for stroke widths.
|
||||
// TODO: Verify the actual behavior; I think it's more like the average between scaleX and scaleY.
|
||||
// Does not yet support vertical/horizontal stroke scaling flags.
|
||||
func (m MatrixTransform) MinimumStrokeWidth() float64 {
|
||||
sx := math.Sqrt(m.GetA()*m.GetA() + m.GetB()*m.GetB())
|
||||
sy := math.Sqrt(m.GetC()*m.GetC() + m.GetD()*m.GetD())
|
||||
return max(sx, sy)
|
||||
}
|
||||
|
||||
func (m MatrixTransform) GetMatrixWithoutTranslation() mat.Matrix {
|
||||
return m.matrix.Slice(0, 2, 0, 2)
|
||||
}
|
||||
|
|
|
@ -106,6 +106,16 @@ func (v Vector2[T]) SubVector(b Vector2[T]) Vector2[T] {
|
|||
}
|
||||
}
|
||||
|
||||
func (v Vector2[T]) Normals() (a, b Vector2[T]) {
|
||||
return Vector2[T]{
|
||||
X: -v.Y,
|
||||
Y: v.X,
|
||||
}, Vector2[T]{
|
||||
X: v.Y,
|
||||
Y: -v.X,
|
||||
}
|
||||
}
|
||||
|
||||
func (v Vector2[T]) Abs() Vector2[T] {
|
||||
x := v.X
|
||||
if x < 0 {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
type ActivePath struct {
|
||||
Segment PathSegment
|
||||
Segment PathSegment[types.Twip]
|
||||
StyleId int
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ func NewActivePath(styleId int, start math.Vector2[types.Twip]) *ActivePath {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *ActivePath) AddPoint(point VisitedPoint) {
|
||||
func (p *ActivePath) AddPoint(point VisitedPoint[types.Twip]) {
|
||||
p.Segment.AddPoint(point)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,20 @@ func (p DrawPath) ApplyMatrixTransform(transform math.MatrixTransform, applyTran
|
|||
}
|
||||
}
|
||||
|
||||
func (p DrawPath) ApplyColorTransform(transform math.ColorTransform) (r DrawPath) {
|
||||
if p.Clip == nil {
|
||||
return DrawPath{
|
||||
Style: p.Style.ApplyColorTransform(transform),
|
||||
Commands: p.Commands,
|
||||
}
|
||||
}
|
||||
return DrawPath{
|
||||
Style: p.Style.ApplyColorTransform(transform),
|
||||
Commands: p.Commands,
|
||||
Clip: p.Clip,
|
||||
}
|
||||
}
|
||||
|
||||
func DrawPathFill(record *FillStyleRecord, shape *Shape, clip *ClipPath) DrawPath {
|
||||
return DrawPath{
|
||||
Style: record,
|
||||
|
|
|
@ -42,11 +42,8 @@ func (l DrawPathList) Fill(shape *Shape) (r DrawPathList) {
|
|||
|
||||
func (l DrawPathList) ApplyColorTransform(transform math.ColorTransform) Fillable {
|
||||
r := make(DrawPathList, 0, len(l))
|
||||
for _, e := range l {
|
||||
r = append(r, DrawPath{
|
||||
Style: e.Style.ApplyColorTransform(transform),
|
||||
Commands: e.Commands,
|
||||
})
|
||||
for i := range l {
|
||||
r = append(r, l[i].ApplyColorTransform(transform))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
29
types/shapes/LineStyleRecord.go
Normal file
29
types/shapes/LineStyleRecord.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package shapes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
)
|
||||
|
||||
type LineStyleRecord struct {
|
||||
Width float64
|
||||
Color math.Color
|
||||
Blur float64
|
||||
}
|
||||
|
||||
func (r *LineStyleRecord) StrokeWidth(transform math.MatrixTransform) float64 {
|
||||
// Flash renders strokes with a 1px minimum width.
|
||||
minWidth := transform.MinimumStrokeWidth()
|
||||
return 0.5 * max(r.Width, minWidth)
|
||||
}
|
||||
|
||||
func (r *LineStyleRecord) ApplyMatrixTransform(transform math.MatrixTransform, applyTranslation bool) StyleRecord {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *LineStyleRecord) ApplyColorTransform(transform math.ColorTransform) StyleRecord {
|
||||
return &LineStyleRecord{
|
||||
Width: r.Width,
|
||||
Color: transform.ApplyToColor(r.Color),
|
||||
Blur: r.Blur,
|
||||
}
|
||||
}
|
|
@ -1,17 +1,16 @@
|
|||
package shapes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/swf/types"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/records"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type PathSegment []VisitedPoint
|
||||
type PathSegment[T ~float64 | ~int64] []VisitedPoint[T]
|
||||
|
||||
func NewPathSegment(start math.Vector2[types.Twip]) PathSegment {
|
||||
return PathSegment{
|
||||
VisitedPoint{
|
||||
func NewPathSegment[T ~float64 | ~int64](start math.Vector2[T]) PathSegment[T] {
|
||||
return PathSegment[T]{
|
||||
VisitedPoint[T]{
|
||||
Pos: start,
|
||||
IsBezierControl: false,
|
||||
},
|
||||
|
@ -23,39 +22,39 @@ func NewPathSegment(start math.Vector2[types.Twip]) PathSegment {
|
|||
// Flash fill paths are dual-sided, with fill style 1 indicating the positive side
|
||||
// and fill style 0 indicating the negative. We have to flip fill style 0 paths
|
||||
// in order to link them to fill style 1 paths.
|
||||
func (s *PathSegment) Flip() {
|
||||
func (s *PathSegment[T]) Flip() {
|
||||
slices.Reverse(*s)
|
||||
}
|
||||
|
||||
func (s *PathSegment) AddPoint(p VisitedPoint) {
|
||||
func (s *PathSegment[T]) AddPoint(p VisitedPoint[T]) {
|
||||
*s = append(*s, p)
|
||||
}
|
||||
|
||||
func (s *PathSegment) Start() math.Vector2[types.Twip] {
|
||||
func (s *PathSegment[T]) Start() math.Vector2[T] {
|
||||
return (*s)[0].Pos
|
||||
}
|
||||
|
||||
func (s *PathSegment) End() math.Vector2[types.Twip] {
|
||||
func (s *PathSegment[T]) End() math.Vector2[T] {
|
||||
return (*s)[len(*s)-1].Pos
|
||||
}
|
||||
|
||||
func (s *PathSegment) IsEmpty() bool {
|
||||
func (s *PathSegment[T]) IsEmpty() bool {
|
||||
return len(*s) <= 1
|
||||
}
|
||||
|
||||
func (s *PathSegment) IsClosed() bool {
|
||||
func (s *PathSegment[T]) IsClosed() bool {
|
||||
return s.Start().Equals(s.End())
|
||||
}
|
||||
|
||||
func (s *PathSegment) Swap(o *PathSegment) {
|
||||
func (s *PathSegment[T]) Swap(o *PathSegment[T]) {
|
||||
*s, *o = *o, *s
|
||||
}
|
||||
|
||||
func (s *PathSegment) Merge(o PathSegment) {
|
||||
func (s *PathSegment[T]) Merge(o PathSegment[T]) {
|
||||
*s = append(*s, o[1:]...)
|
||||
}
|
||||
|
||||
func (s *PathSegment) TryMerge(o *PathSegment, isDirected bool) bool {
|
||||
func (s *PathSegment[T]) TryMerge(o *PathSegment[T], isDirected bool) bool {
|
||||
if o.End().Equals(s.Start()) {
|
||||
s.Swap(o)
|
||||
s.Merge(*o)
|
||||
|
@ -77,7 +76,7 @@ func (s *PathSegment) TryMerge(o *PathSegment, isDirected bool) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (s *PathSegment) GetShape() *Shape {
|
||||
func (s *PathSegment[T]) GetShape() *Shape {
|
||||
if s.IsEmpty() {
|
||||
panic("not possible")
|
||||
}
|
||||
|
@ -88,7 +87,7 @@ func (s *PathSegment) GetShape() *Shape {
|
|||
|
||||
points := *s
|
||||
|
||||
next := func() VisitedPoint {
|
||||
next := func() VisitedPoint[T] {
|
||||
point := points[0]
|
||||
points = points[1:]
|
||||
return point
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
package shapes
|
||||
|
||||
import "slices"
|
||||
import (
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/swf/types"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type PendingPathMap map[int]*PendingPath
|
||||
type PendingPathMap map[int]*PendingPath[types.Twip]
|
||||
|
||||
func (m PendingPathMap) MergePath(p *ActivePath, directed bool) {
|
||||
if _, ok := m[p.StyleId]; !ok {
|
||||
m[p.StyleId] = &PendingPath{}
|
||||
m[p.StyleId] = &PendingPath[types.Twip]{}
|
||||
}
|
||||
m[p.StyleId].MergePath(&p.Segment, directed)
|
||||
}
|
||||
|
||||
type PendingPath []*PathSegment
|
||||
type PendingPath[T ~float64 | ~int64] []*PathSegment[T]
|
||||
|
||||
func (p *PendingPath) MergePath(newSegment *PathSegment, directed bool) {
|
||||
func (p *PendingPath[T]) MergePath(newSegment *PathSegment[T], directed bool) {
|
||||
if !newSegment.IsEmpty() {
|
||||
var merged *PathSegment
|
||||
var merged *PathSegment[T]
|
||||
|
||||
for i, segment := range *p {
|
||||
if segment.TryMerge(newSegment, directed) {
|
||||
|
@ -33,7 +36,7 @@ func (p *PendingPath) MergePath(newSegment *PathSegment, directed bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *PendingPath) GetShape() *Shape {
|
||||
func (p *PendingPath[T]) GetShape() *Shape {
|
||||
shape := &Shape{}
|
||||
for _, segment := range *p {
|
||||
shape = shape.Merge(segment.GetShape())
|
||||
|
|
|
@ -246,7 +246,7 @@ func (c *ShapeConverter) HandleNode(node subtypes.SHAPERECORD) {
|
|||
}
|
||||
|
||||
func (c *ShapeConverter) VisitPoint(pos math.Vector2[types.Twip], isBezierControlPoint bool) {
|
||||
point := VisitedPoint{
|
||||
point := VisitedPoint[types.Twip]{
|
||||
Pos: pos,
|
||||
IsBezierControl: isBezierControlPoint,
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ func (c *ShapeConverter) FlushLayer() {
|
|||
|
||||
//wrap around all segments, even if closed. ASS does NOT like them otherwise. so we draw everything backwards to have border around the line, not just on one side
|
||||
//TODO: using custom line borders later using fills this can be removed
|
||||
var newSegments PendingPath
|
||||
var newSegments PendingPath[types.Twip]
|
||||
for _, segment := range *path {
|
||||
other := slices.Clone(*segment)
|
||||
other.Flip()
|
||||
|
|
|
@ -34,7 +34,7 @@ func StyleListFromSWFItems(collection ObjectCollection, fillStyles subtypes.FILL
|
|||
for _, s := range lineStyles.LineStyles {
|
||||
r.LineStyles = append(r.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.Width), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.Width).Float64(),
|
||||
Color: math.Color{
|
||||
R: s.Color.R(),
|
||||
G: s.Color.G(),
|
||||
|
@ -48,7 +48,7 @@ func StyleListFromSWFItems(collection ObjectCollection, fillStyles subtypes.FILL
|
|||
if !s.Flag.HasFill {
|
||||
r.LineStyles = append(r.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.Width), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.Width).Float64(),
|
||||
Color: math.Color{
|
||||
R: s.Color.R(),
|
||||
G: s.Color.G(),
|
||||
|
@ -62,7 +62,7 @@ func StyleListFromSWFItems(collection ObjectCollection, fillStyles subtypes.FILL
|
|||
case types.Color:
|
||||
r.LineStyles = append(r.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.Width), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.Width).Float64(),
|
||||
Color: math.Color{
|
||||
R: fillEntry.R(),
|
||||
G: fillEntry.G(),
|
||||
|
@ -75,7 +75,7 @@ func StyleListFromSWFItems(collection ObjectCollection, fillStyles subtypes.FILL
|
|||
color := fillEntry.GetItems()[0].Color
|
||||
r.LineStyles = append(r.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.Width), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.Width).Float64(),
|
||||
Color: color,
|
||||
})
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
for _, s := range lineStyles.LineStyles {
|
||||
start.LineStyles = append(start.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.StartWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.StartWidth).Float64(),
|
||||
Color: math.Color{
|
||||
R: s.StartColor.R(),
|
||||
G: s.StartColor.G(),
|
||||
|
@ -107,7 +107,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
|
||||
end.LineStyles = append(end.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.EndWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.EndWidth).Float64(),
|
||||
Color: math.Color{
|
||||
R: s.EndColor.R(),
|
||||
G: s.EndColor.G(),
|
||||
|
@ -121,7 +121,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
if !s.Flag.HasFill {
|
||||
start.LineStyles = append(start.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.StartWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.StartWidth).Float64(),
|
||||
Color: math.Color{
|
||||
R: s.StartColor.R(),
|
||||
G: s.StartColor.G(),
|
||||
|
@ -131,7 +131,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
})
|
||||
end.LineStyles = append(end.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.EndWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.EndWidth).Float64(),
|
||||
Color: math.Color{
|
||||
R: s.EndColor.R(),
|
||||
G: s.EndColor.G(),
|
||||
|
@ -146,7 +146,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
case types.Color:
|
||||
start.LineStyles = append(start.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.StartWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.StartWidth).Float64(),
|
||||
Color: math.Color{
|
||||
R: fillEntry.R(),
|
||||
G: fillEntry.G(),
|
||||
|
@ -159,7 +159,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
color := fillEntry.GetItems()[0].Color
|
||||
start.LineStyles = append(start.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.StartWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.StartWidth).Float64(),
|
||||
Color: color,
|
||||
})
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
case types.Color:
|
||||
end.LineStyles = append(end.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.EndWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.EndWidth).Float64(),
|
||||
Color: math.Color{
|
||||
R: fillEntry.R(),
|
||||
G: fillEntry.G(),
|
||||
|
@ -180,7 +180,7 @@ func StyleListFromSWFMorphItems(collection ObjectCollection, fillStyles subtypes
|
|||
color := fillEntry.GetItems()[0].Color
|
||||
end.LineStyles = append(end.LineStyles, &LineStyleRecord{
|
||||
//TODO: any reason for max(types.TwipFactor)?
|
||||
Width: max(types.Twip(s.EndWidth), types.TwipFactor).Float64(),
|
||||
Width: types.Twip(s.EndWidth).Float64(),
|
||||
Color: color,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,20 +11,7 @@ import (
|
|||
|
||||
type StyleRecord interface {
|
||||
ApplyColorTransform(transform math.ColorTransform) StyleRecord
|
||||
}
|
||||
|
||||
type LineStyleRecord struct {
|
||||
Width float64
|
||||
Color math.Color
|
||||
Blur float64
|
||||
}
|
||||
|
||||
func (r *LineStyleRecord) ApplyColorTransform(transform math.ColorTransform) StyleRecord {
|
||||
return &LineStyleRecord{
|
||||
Width: r.Width,
|
||||
Color: transform.ApplyToColor(r.Color),
|
||||
Blur: r.Blur,
|
||||
}
|
||||
ApplyMatrixTransform(transform math.MatrixTransform, applyTranslation bool) StyleRecord
|
||||
}
|
||||
|
||||
type Fillable interface {
|
||||
|
@ -74,6 +61,17 @@ func (r *FillStyleRecord) Flatten(s *Shape) DrawPathList {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *FillStyleRecord) ApplyMatrixTransform(transform math.MatrixTransform, applyTranslation bool) StyleRecord {
|
||||
if r.Border != nil {
|
||||
return &FillStyleRecord{
|
||||
Fill: r.Fill,
|
||||
Border: r.Border.ApplyMatrixTransform(transform, applyTranslation).(*LineStyleRecord),
|
||||
Blur: r.Blur, //TODO: scale blur?
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *FillStyleRecord) ApplyColorTransform(transform math.ColorTransform) StyleRecord {
|
||||
fill := r.Fill
|
||||
if color, ok := fill.(math.Color); ok {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package shapes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/swf/types"
|
||||
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
|
||||
)
|
||||
|
||||
type VisitedPoint struct {
|
||||
Pos math.Vector2[types.Twip]
|
||||
type VisitedPoint[T ~float64 | ~int64] struct {
|
||||
Pos math.Vector2[T]
|
||||
|
||||
IsBezierControl bool
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue