swf2ass-go/types/shapes/LinearGradient.go

111 lines
3.2 KiB
Go

package shapes
import (
swfsubtypes "git.gammaspectra.live/WeebDataHoarder/swf-go/subtypes"
"git.gammaspectra.live/WeebDataHoarder/swf-go/types"
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/settings"
"git.gammaspectra.live/WeebDataHoarder/swf2ass-go/types/math"
)
func interpolateLinearGradient(self Gradient, overlap, blur float64, gradientSlices int, bb Rectangle[float64]) DrawPathList {
//items is max size 8 to 15 depending on SWF version
height0 := GradientBoundsMin.Float64()
height1 := GradientBoundsMax.Float64()
switch self.SpreadMode {
case swfsubtypes.GradientSpreadPad:
height0 = min(height0, bb.TopLeft.Y)
height1 = max(height1, bb.BottomRight.Y)
}
topLeft0 := math.NewVector2(GradientBoundsMin.Float64(), height0)
topLeft1 := math.NewVector2(GradientBoundsMax.Float64(), height0)
bottomRight0 := math.NewVector2(GradientBoundsMin.Float64(), height1)
bottomRight1 := math.NewVector2(GradientBoundsMax.Float64(), height1)
//TODO: more spreadMode, generalize
vOverlap := math.NewVector2(overlap, 0).Divide(2)
items := self.Interpolate(gradientSlices)
if !settings.GlobalSettings.GradientApplyOverlapOnTransparency {
for _, i := range items {
if i.Color.Alpha != 255 {
//transparency! remove overlaps
blur = 0
overlap = 0
break
}
}
}
var paths DrawPathList
for _, item := range items {
if item.Start == 0 {
switch self.SpreadMode {
case swfsubtypes.GradientSpreadPad:
if bb.TopLeft.X < topLeft0.X {
paths = append(paths, DrawPathFill(
&FillStyleRecord{
Fill: item.Color,
Blur: blur,
},
Rectangle[float64]{
TopLeft: math.NewVector2(bb.TopLeft.X, height0),
BottomRight: math.NewVector2(topLeft0.X, height1).AddVector(vOverlap),
}.Draw(),
))
}
}
}
paths = append(paths, DrawPathFill(
&FillStyleRecord{
Fill: item.Color,
Blur: blur,
},
Rectangle[float64]{
TopLeft: math.LerpVector2(topLeft0, topLeft1, item.Start).SubVector(vOverlap),
BottomRight: math.LerpVector2(bottomRight0, bottomRight1, item.End).AddVector(vOverlap),
}.Draw(),
))
if item.End == 1 {
switch self.SpreadMode {
case swfsubtypes.GradientSpreadPad:
if bb.BottomRight.X > bottomRight1.X {
paths = append(paths, DrawPathFill(
&FillStyleRecord{
Fill: item.Color,
Blur: blur,
},
Rectangle[float64]{
TopLeft: math.NewVector2(topLeft1.X, height0).SubVector(vOverlap),
BottomRight: math.NewVector2(bb.BottomRight.X, height1),
}.Draw(),
))
}
}
}
}
return paths
}
func LinearGradientFromSWF(records []swfsubtypes.GRADRECORD, transform types.MATRIX, spreadMode swfsubtypes.GradientSpreadMode, interpolationMode swfsubtypes.GradientInterpolationMode) Gradient {
items := make([]GradientItem, 0, len(records))
for _, r := range records {
items = append(items, GradientItemFromSWF(r.Ratio, r.Color))
}
//TODO: interpolationMode, spreadMode
return Gradient{
Records: items,
Transform: math.MatrixTransformFromSWF(transform, 1),
SpreadMode: spreadMode,
InterpolationMode: interpolationMode,
Interpolation: interpolateLinearGradient,
}
}