blob: 8cfb558f9751e50946bc2c530f3f1e845f1514b1 [file] [log] [blame]
// Package scrap defines the scrap types and functions on them.
package scrap
import (
"fmt"
"regexp"
"strconv"
"strings"
"go.skia.org/infra/go/skerr"
)
var (
uniformFloatScalarRegex = regexp.MustCompile(`^float([234]?)$`)
uniformFloatMatrixRegex = regexp.MustCompile(`^float([234])x([234])$`)
)
// uniformValue represents a single instance of a uniform definition
// in a shader script. For example a definition like:
//
// uniform float3 iColor;
//
// will have a Name of "iColor", and a Type of "float3".
type uniformValue struct {
Name string
Type string
}
// numFloats will return the number of floats needed to represent a
// uniformValue.
func (u uniformValue) numFloats() (int, error) {
if u.Type == "float" {
return 1, nil
}
m := uniformFloatScalarRegex.FindStringSubmatch(u.Type)
if m != nil {
n, err := strconv.Atoi(m[1])
if err != nil {
return 0, skerr.Wrap(err)
}
return n, nil
}
if m = uniformFloatMatrixRegex.FindStringSubmatch(u.Type); m != nil {
x, err := strconv.Atoi(m[1])
if err != nil {
return 0, skerr.Wrap(err)
}
y, err := strconv.Atoi(m[2])
if err != nil {
return 0, skerr.Wrap(err)
}
return x * y, nil
}
return 0, skerr.Fmt("Can't determine size of %q", u.Type)
}
// floatSliceToString will convert a slice of float32's to a string
// representation. e.g. []float{0, 1,2,3} will become "0.0f, 1.0f, 2.0f, 3.0f"
func floatSliceToString(floats []float32) string {
strs := make([]string, len(floats))
for i := 0; i < len(floats); i++ {
strs[i] = fmt.Sprintf("%g", floats[i]) // A C++ float literal.
if !strings.Contains(strs[i], ".") {
strs[i] = strs[i] + ".0"
}
strs[i] = strs[i] + "f"
}
return strings.Join(strs, ", ")
}
// getCppDefinitionString return a string, which is valid C++ code, to define
// a uniform value in a builder.
func (u uniformValue) getCppDefinitionString(vals []float32, suffix string) (string, error) {
switch u.Type {
case "float":
return fmt.Sprintf(`builder%s.uniform("%s") = %s;`, suffix, u.Name, floatSliceToString(vals[0:1])), nil
case "float2":
return fmt.Sprintf(`builder%s.uniform("%s") = SkV2{%s};`, suffix, u.Name, floatSliceToString(vals[0:2])), nil
case "float3":
return fmt.Sprintf(`builder%s.uniform("%s") = SkV3{%s};`, suffix, u.Name, floatSliceToString(vals[0:3])), nil
case "float4":
return fmt.Sprintf(`builder%s.uniform("%s") = SkV4{%s};`, suffix, u.Name, floatSliceToString(vals[0:4])), nil
case "float2x2":
return fmt.Sprintf(`builder%s.uniform("%s") = SkV4{%s};`, suffix, u.Name, floatSliceToString(vals[0:4])), nil
}
return "", skerr.Fmt("Unsupported uniform type %q", u.Type)
}