Ejemplo n.º 1
0
// mix takes two colors and optional weight (50% assumed). mix evaluates the
// difference of alphas and factors this into the weight calculations
// For details see: http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method
func mix(call *ast.CallExpr, args ...*ast.BasicLit) (*ast.BasicLit, error) {
	wt, err := strconv.ParseFloat(args[2].Value, 8)
	// Parse percentage ie. 50%
	if err != nil {
		var i float64
		_, err := fmt.Sscanf(args[2].Value, "%f%%", &i)
		if err != nil {
			log.Fatal(err)
		}
		wt = i / 100
	}

	c1, err := ast.ColorFromHexString(args[0].Value)
	if err != nil {
		return nil, fmt.Errorf("failed to read hex string %s: %s",
			args[0].Value, err)
	}
	c2, err := ast.ColorFromHexString(args[1].Value)
	if err != nil {
		return nil, fmt.Errorf("failed to read hex string %s: %s",
			args[1].Value, err)
	}

	var r, g, b, a float64

	a1, a2 := float64(c1.A)/100, float64(c2.A)/100
	w := wt*2 - 1
	a = a1 - a2

	var w1 float64
	// if w*a == -1, weight is w
	if w*a == -1 {
		w1 = w
	} else {
		w1 = (w + a) / (1 + w*a)
	}
	w1 = (w1 + 1) / 2
	w2 := 1 - w1

	r = w1*float64(c1.R) + w2*float64(c2.R)
	g = w1*float64(c1.G) + w2*float64(c2.G)
	b = w1*float64(c1.B) + w2*float64(c2.B)

	alpha := (float64(c1.A) + float64(c2.A)) / 2

	ret := color.RGBA{
		R: uint8(round(r, 0)),
		G: uint8(round(g, 0)),
		B: uint8(round(b, 0)),
		A: uint8(round(alpha, 2)),
	}

	return colorOutput(ret, call.Args[0]), nil
}
Ejemplo n.º 2
0
func invert(call *ast.CallExpr, args ...*ast.BasicLit) (*ast.BasicLit, error) {
	val := args[0].Value
	c, err := ast.ColorFromHexString(val)
	if err != nil {
		return nil, fmt.Errorf("invert failed to parse argument %s; %s", val, err)
	}

	c.R = 255 - c.R
	c.G = 255 - c.G
	c.B = 255 - c.B

	return colorOutput(c, call.Args[0]), nil
}
Ejemplo n.º 3
0
func parseColors(args []*ast.BasicLit) (color.RGBA, error) {
	ints := make([]uint8, 4)
	var ret color.RGBA
	var u uint8
	for i := range args {
		v := args[i]
		switch v.Kind {
		case token.FLOAT:
			f, err := strconv.ParseFloat(args[i].Value, 8)
			if err != nil {
				return ret, err
			}
			// Has to be alpha, or bust
			u = uint8(f * 100)
		case token.INT:
			i, err := strconv.Atoi(v.Value)
			if err != nil {
				return ret, err
			}
			u = uint8(i)
		case token.COLOR:
			if i != 0 {
				return ret, fmt.Errorf("hex is only allowed as the first argumetn found: % #v", v)
			}
			var err error
			ret, err = ast.ColorFromHexString(v.Value)
			if err != nil {
				return ret, err
			}
			// This is only allowed as the first argument
			i = i + 2
		default:
			log.Fatalf("unsupported kind %s % #v\n", v.Kind, v)
		}
		ints[i] = u
	}
	if ints[0] > 0 {
		ret.R = ints[0]
	}
	if ints[1] > 0 {
		ret.G = ints[1]
	}
	if ints[2] > 0 {
		ret.B = ints[2]
	}
	if ints[3] > 0 {
		ret.A = ints[3]
	}
	return ret, nil
}