in draw/gen.go [207:703]
func expnDollar(prefix, dollar, suffix string, d *data) string {
switch dollar {
case "dType":
return prefix + d.dType + suffix
case "dTypeRN":
return prefix + relName(d.dType) + suffix
case "sratio":
return prefix + d.sratio + suffix
case "sType":
return prefix + d.sType + suffix
case "sTypeRN":
return prefix + relName(d.sType) + suffix
case "receiver":
return prefix + d.receiver + suffix
case "op":
return prefix + d.op + suffix
case "switch":
return expnSwitch("", "", true, suffix)
case "switchD":
return expnSwitch("", "", false, suffix)
case "switchS":
return expnSwitch("", "anyDType", false, suffix)
case "preOuter":
switch d.dType {
default:
return ";"
case "Image":
s := ""
if d.sType == "image.Image" {
s = "srcMask, smp := opts.SrcMask, opts.SrcMaskP\n"
}
return s +
"dstMask, dmp := opts.DstMask, opts.DstMaskP\n" +
"dstColorRGBA64 := &color.RGBA64{}\n" +
"dstColor := color.Color(dstColorRGBA64)"
}
case "preInner":
switch d.dType {
default:
return ";"
case "*image.RGBA":
return "d := " + pixOffset("dst", "dr.Min.X+adr.Min.X", "dr.Min.Y+int(dy)", "*4", "*dst.Stride")
}
case "preKernelOuter":
switch d.sType {
default:
return ";"
case "image.Image":
return "srcMask, smp := opts.SrcMask, opts.SrcMaskP"
}
case "preKernelInner":
switch d.dType {
default:
return ";"
case "*image.RGBA":
return "d := " + pixOffset("dst", "dr.Min.X+int(dx)", "dr.Min.Y+adr.Min.Y", "*4", "*dst.Stride")
}
case "blend":
args, _ := splitArgs(suffix)
if len(args) != 4 {
return ""
}
switch d.sType {
default:
return argf(args, ""+
"$3r = $0*$1r + $2*$3r\n"+
"$3g = $0*$1g + $2*$3g\n"+
"$3b = $0*$1b + $2*$3b\n"+
"$3a = $0*$1a + $2*$3a",
)
case "*image.Gray":
return argf(args, ""+
"$3r = $0*$1r + $2*$3r",
)
case "*image.YCbCr":
return argf(args, ""+
"$3r = $0*$1r + $2*$3r\n"+
"$3g = $0*$1g + $2*$3g\n"+
"$3b = $0*$1b + $2*$3b",
)
}
case "clampToAlpha":
if alwaysOpaque[d.sType] {
return ";"
}
// Go uses alpha-premultiplied color. The naive computation can lead to
// invalid colors, e.g. red > alpha, when some weights are negative.
return `
if pr > pa {
pr = pa
}
if pg > pa {
pg = pa
}
if pb > pa {
pb = pa
}
`
case "convFtou":
args, _ := splitArgs(suffix)
if len(args) != 2 {
return ""
}
switch d.sType {
default:
return argf(args, ""+
"$0r := uint32($1r)\n"+
"$0g := uint32($1g)\n"+
"$0b := uint32($1b)\n"+
"$0a := uint32($1a)",
)
case "*image.Gray":
return argf(args, ""+
"$0r := uint32($1r)",
)
case "*image.YCbCr":
return argf(args, ""+
"$0r := uint32($1r)\n"+
"$0g := uint32($1g)\n"+
"$0b := uint32($1b)",
)
}
case "outputu":
args, _ := splitArgs(suffix)
if len(args) != 3 {
return ""
}
switch d.op {
case "Over":
switch d.dType {
default:
log.Fatalf("bad dType %q", d.dType)
case "Image":
return argf(args, ""+
"qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
"if dstMask != nil {\n"+
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
" $2r = $2r * ma / 0xffff\n"+
" $2g = $2g * ma / 0xffff\n"+
" $2b = $2b * ma / 0xffff\n"+
" $2a = $2a * ma / 0xffff\n"+
"}\n"+
"$2a1 := 0xffff - $2a\n"+
"dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
"dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
"dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
"dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
"dst.Set($0, $1, dstColor)",
)
case "*image.RGBA":
return argf(args, ""+
"$2a1 := (0xffff - $2a) * 0x101\n"+
"dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*$2a1/0xffff + $2r) >> 8)\n"+
"dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*$2a1/0xffff + $2g) >> 8)\n"+
"dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*$2a1/0xffff + $2b) >> 8)\n"+
"dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*$2a1/0xffff + $2a) >> 8)",
)
}
case "Src":
switch d.dType {
default:
log.Fatalf("bad dType %q", d.dType)
case "Image":
return argf(args, ""+
"if dstMask != nil {\n"+
" qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
" pr = pr * ma / 0xffff\n"+
" pg = pg * ma / 0xffff\n"+
" pb = pb * ma / 0xffff\n"+
" pa = pa * ma / 0xffff\n"+
" $2a1 := 0xffff - ma\n"+ // Note that this is ma, not $2a.
" dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
" dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
" dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
" dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
" dst.Set($0, $1, dstColor)\n"+
"} else {\n"+
" dstColorRGBA64.R = uint16($2r)\n"+
" dstColorRGBA64.G = uint16($2g)\n"+
" dstColorRGBA64.B = uint16($2b)\n"+
" dstColorRGBA64.A = uint16($2a)\n"+
" dst.Set($0, $1, dstColor)\n"+
"}",
)
case "*image.RGBA":
switch d.sType {
default:
return argf(args, ""+
"dst.Pix[d+0] = uint8($2r >> 8)\n"+
"dst.Pix[d+1] = uint8($2g >> 8)\n"+
"dst.Pix[d+2] = uint8($2b >> 8)\n"+
"dst.Pix[d+3] = uint8($2a >> 8)",
)
case "*image.Gray":
return argf(args, ""+
"out := uint8($2r >> 8)\n"+
"dst.Pix[d+0] = out\n"+
"dst.Pix[d+1] = out\n"+
"dst.Pix[d+2] = out\n"+
"dst.Pix[d+3] = 0xff",
)
case "*image.YCbCr":
return argf(args, ""+
"dst.Pix[d+0] = uint8($2r >> 8)\n"+
"dst.Pix[d+1] = uint8($2g >> 8)\n"+
"dst.Pix[d+2] = uint8($2b >> 8)\n"+
"dst.Pix[d+3] = 0xff",
)
}
}
}
case "outputf":
args, _ := splitArgs(suffix)
if len(args) != 5 {
return ""
}
ret := ""
switch d.op {
case "Over":
switch d.dType {
default:
log.Fatalf("bad dType %q", d.dType)
case "Image":
ret = argf(args, ""+
"qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
"$3r0 := uint32($2($3r * $4))\n"+
"$3g0 := uint32($2($3g * $4))\n"+
"$3b0 := uint32($2($3b * $4))\n"+
"$3a0 := uint32($2($3a * $4))\n"+
"if dstMask != nil {\n"+
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
" $3r0 = $3r0 * ma / 0xffff\n"+
" $3g0 = $3g0 * ma / 0xffff\n"+
" $3b0 = $3b0 * ma / 0xffff\n"+
" $3a0 = $3a0 * ma / 0xffff\n"+
"}\n"+
"$3a1 := 0xffff - $3a0\n"+
"dstColorRGBA64.R = uint16(qr*$3a1/0xffff + $3r0)\n"+
"dstColorRGBA64.G = uint16(qg*$3a1/0xffff + $3g0)\n"+
"dstColorRGBA64.B = uint16(qb*$3a1/0xffff + $3b0)\n"+
"dstColorRGBA64.A = uint16(qa*$3a1/0xffff + $3a0)\n"+
"dst.Set($0, $1, dstColor)",
)
case "*image.RGBA":
ret = argf(args, ""+
"$3r0 := uint32($2($3r * $4))\n"+
"$3g0 := uint32($2($3g * $4))\n"+
"$3b0 := uint32($2($3b * $4))\n"+
"$3a0 := uint32($2($3a * $4))\n"+
"$3a1 := (0xffff - uint32($3a0)) * 0x101\n"+
"dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*$3a1/0xffff + $3r0) >> 8)\n"+
"dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*$3a1/0xffff + $3g0) >> 8)\n"+
"dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*$3a1/0xffff + $3b0) >> 8)\n"+
"dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*$3a1/0xffff + $3a0) >> 8)",
)
}
case "Src":
switch d.dType {
default:
log.Fatalf("bad dType %q", d.dType)
case "Image":
ret = argf(args, ""+
"if dstMask != nil {\n"+
" qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
" pr := uint32($2($3r * $4)) * ma / 0xffff\n"+
" pg := uint32($2($3g * $4)) * ma / 0xffff\n"+
" pb := uint32($2($3b * $4)) * ma / 0xffff\n"+
" pa := uint32($2($3a * $4)) * ma / 0xffff\n"+
" pa1 := 0xffff - ma\n"+ // Note that this is ma, not pa.
" dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)\n"+
" dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)\n"+
" dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)\n"+
" dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)\n"+
" dst.Set($0, $1, dstColor)\n"+
"} else {\n"+
" dstColorRGBA64.R = $2($3r * $4)\n"+
" dstColorRGBA64.G = $2($3g * $4)\n"+
" dstColorRGBA64.B = $2($3b * $4)\n"+
" dstColorRGBA64.A = $2($3a * $4)\n"+
" dst.Set($0, $1, dstColor)\n"+
"}",
)
case "*image.RGBA":
switch d.sType {
default:
ret = argf(args, ""+
"dst.Pix[d+0] = uint8($2($3r * $4) >> 8)\n"+
"dst.Pix[d+1] = uint8($2($3g * $4) >> 8)\n"+
"dst.Pix[d+2] = uint8($2($3b * $4) >> 8)\n"+
"dst.Pix[d+3] = uint8($2($3a * $4) >> 8)",
)
case "*image.Gray":
ret = argf(args, ""+
"out := uint8($2($3r * $4) >> 8)\n"+
"dst.Pix[d+0] = out\n"+
"dst.Pix[d+1] = out\n"+
"dst.Pix[d+2] = out\n"+
"dst.Pix[d+3] = 0xff",
)
case "*image.YCbCr":
ret = argf(args, ""+
"dst.Pix[d+0] = uint8($2($3r * $4) >> 8)\n"+
"dst.Pix[d+1] = uint8($2($3g * $4) >> 8)\n"+
"dst.Pix[d+2] = uint8($2($3b * $4) >> 8)\n"+
"dst.Pix[d+3] = 0xff",
)
}
}
}
return strings.Replace(ret, " * 1)", ")", -1)
case "srcf", "srcu":
lhs, eqOp := splitEq(prefix)
if lhs == "" {
return ""
}
args, extra := splitArgs(suffix)
if len(args) != 2 {
return ""
}
tmp := ""
if dollar == "srcf" {
tmp = "u"
}
// TODO: there's no need to multiply by 0x101 in the switch below if
// the next thing we're going to do is shift right by 8.
buf := new(bytes.Buffer)
switch d.sType {
default:
log.Fatalf("bad sType %q", d.sType)
case "image.Image":
fmt.Fprintf(buf, ""+
"%sr%s, %sg%s, %sb%s, %sa%s := src.At(%s, %s).RGBA()\n",
lhs, tmp, lhs, tmp, lhs, tmp, lhs, tmp, args[0], args[1],
)
if d.dType == "" || d.dType == "Image" {
fmt.Fprintf(buf, ""+
"if srcMask != nil {\n"+
" _, _, _, ma := srcMask.At(smp.X+%s, smp.Y+%s).RGBA()\n"+
" %sr%s = %sr%s * ma / 0xffff\n"+
" %sg%s = %sg%s * ma / 0xffff\n"+
" %sb%s = %sb%s * ma / 0xffff\n"+
" %sa%s = %sa%s * ma / 0xffff\n"+
"}\n",
args[0], args[1],
lhs, tmp, lhs, tmp,
lhs, tmp, lhs, tmp,
lhs, tmp, lhs, tmp,
lhs, tmp, lhs, tmp,
)
}
case "*image.Gray":
fmt.Fprintf(buf, ""+
"%si := %s\n"+
"%sr%s := uint32(src.Pix[%si]) * 0x101\n",
lhs, pixOffset("src", args[0], args[1], "", "*src.Stride"),
lhs, tmp, lhs,
)
case "*image.NRGBA":
fmt.Fprintf(buf, ""+
"%si := %s\n"+
"%sa%s := uint32(src.Pix[%si+3]) * 0x101\n"+
"%sr%s := uint32(src.Pix[%si+0]) * %sa%s / 0xff\n"+
"%sg%s := uint32(src.Pix[%si+1]) * %sa%s / 0xff\n"+
"%sb%s := uint32(src.Pix[%si+2]) * %sa%s / 0xff\n",
lhs, pixOffset("src", args[0], args[1], "*4", "*src.Stride"),
lhs, tmp, lhs,
lhs, tmp, lhs, lhs, tmp,
lhs, tmp, lhs, lhs, tmp,
lhs, tmp, lhs, lhs, tmp,
)
case "*image.RGBA":
fmt.Fprintf(buf, ""+
"%si := %s\n"+
"%sr%s := uint32(src.Pix[%si+0]) * 0x101\n"+
"%sg%s := uint32(src.Pix[%si+1]) * 0x101\n"+
"%sb%s := uint32(src.Pix[%si+2]) * 0x101\n"+
"%sa%s := uint32(src.Pix[%si+3]) * 0x101\n",
lhs, pixOffset("src", args[0], args[1], "*4", "*src.Stride"),
lhs, tmp, lhs,
lhs, tmp, lhs,
lhs, tmp, lhs,
lhs, tmp, lhs,
)
case "*image.YCbCr":
fmt.Fprintf(buf, ""+
"%si := %s\n"+
"%sj := %s\n"+
"%s\n",
lhs, pixOffset("src", args[0], args[1], "", "*src.YStride"),
lhs, cOffset(args[0], args[1], d.sratio),
ycbcrToRGB(lhs, tmp),
)
}
if dollar == "srcf" {
switch d.sType {
default:
fmt.Fprintf(buf, ""+
"%sr %s float64(%sru)%s\n"+
"%sg %s float64(%sgu)%s\n"+
"%sb %s float64(%sbu)%s\n"+
"%sa %s float64(%sau)%s\n",
lhs, eqOp, lhs, extra,
lhs, eqOp, lhs, extra,
lhs, eqOp, lhs, extra,
lhs, eqOp, lhs, extra,
)
case "*image.Gray":
fmt.Fprintf(buf, ""+
"%sr %s float64(%sru)%s\n",
lhs, eqOp, lhs, extra,
)
case "*image.YCbCr":
fmt.Fprintf(buf, ""+
"%sr %s float64(%sru)%s\n"+
"%sg %s float64(%sgu)%s\n"+
"%sb %s float64(%sbu)%s\n",
lhs, eqOp, lhs, extra,
lhs, eqOp, lhs, extra,
lhs, eqOp, lhs, extra,
)
}
}
return strings.TrimSpace(buf.String())
case "tweakD":
if d.dType == "*image.RGBA" {
return "d += dst.Stride"
}
return ";"
case "tweakDx":
if d.dType == "*image.RGBA" {
return strings.Replace(prefix, "dx++", "dx, d = dx+1, d+4", 1)
}
return prefix
case "tweakDy":
if d.dType == "*image.RGBA" {
return strings.Replace(prefix, "for dy, s", "for _, s", 1)
}
return prefix
case "tweakP":
switch d.sType {
case "*image.Gray":
if strings.HasPrefix(strings.TrimSpace(prefix), "pa * ") {
return "1,"
}
return "pr,"
case "*image.YCbCr":
if strings.HasPrefix(strings.TrimSpace(prefix), "pa * ") {
return "1,"
}
}
return prefix
case "tweakPr":
if d.sType == "*image.Gray" {
return "pr *= s.invTotalWeightFFFF"
}
return ";"
case "tweakVarP":
switch d.sType {
case "*image.Gray":
return strings.Replace(prefix, "var pr, pg, pb, pa", "var pr", 1)
case "*image.YCbCr":
return strings.Replace(prefix, "var pr, pg, pb, pa", "var pr, pg, pb", 1)
}
return prefix
}
return ""
}