public static Value Darken(IEnumerable<Value> parameters, IPosition position) { if (parameters.Count() != 2) { Current.RecordError(ErrorType.Compiler, position, "Darken expects a color parameter, and a percentage"); return ExcludeFromOutputValue.Singleton; } var color = parameters.ElementAt(0); var percent = parameters.ElementAt(1); if (!(color is ColorValue)) { Current.RecordError(ErrorType.Compiler, position, "Darken expects a color as its first parameter, found [" + color + "]"); return ExcludeFromOutputValue.Singleton; } if (!(percent is NumberWithUnitValue)) { Current.RecordError(ErrorType.Compiler, position, "Darken expects a percentage as its second parameter, found [" + percent + "]"); return ExcludeFromOutputValue.Singleton; } var colorV = (ColorValue)color; var percentV = (NumberWithUnitValue)percent; if (percentV.Unit != Unit.Percent) { Current.RecordError(ErrorType.Compiler, position, "Darken expects a percentage as its second parameter, found [" + percent + "]"); return ExcludeFromOutputValue.Singleton; } var hsl = ConvertToHSL(colorV, position); if (hsl == null) return ExcludeFromOutputValue.Singleton; var h = new NumberValue(hsl.Item1); var s = new NumberWithUnitValue(hsl.Item2 * 100m, Unit.Percent); var l = decimal.Round(hsl.Item3 - percentV.Value / 100m, 2); if (l < 0m) l = 0m; return new HSLColorValue(h, s, new NumberWithUnitValue(l * 100m, Unit.Percent)); }
public static Value Round(IEnumerable<Value> parameters, IPosition position) { if (parameters.Count() < 1 || parameters.Count() > 2) { Current.RecordError(ErrorType.Compiler, position, "Round expects 1 or 2 numeric parameters"); return ExcludeFromOutputValue.Singleton; } if (parameters.Any(a => a is ExcludeFromOutputValue)) return ExcludeFromOutputValue.Singleton; if (parameters.Any(a => a is NotFoundValue)) return NotFoundValue.Default.BindToPosition(position.Start, position.Stop, position.FilePath); var toRound = parameters.ElementAt(0); Value precision = new NumberValue(0); if (parameters.Count() == 2) { precision = parameters.ElementAt(1); } if (!(toRound is NumberValue)) { Current.RecordError(ErrorType.Compiler, position, "Round expects a number, with optional unit, as its first parameter; found [" + toRound + "]"); return ExcludeFromOutputValue.Singleton; } if (!(precision is NumberValue) || precision is NumberWithUnitValue) { Current.RecordError(ErrorType.Compiler, position, "Round expects a number, without a unit, as its second parameter; found [" + precision + "]"); return ExcludeFromOutputValue.Singleton; } var nPrecision = ((NumberValue)precision).Value; if ((int)nPrecision != nPrecision) { Current.RecordError(ErrorType.Compiler, position, "Round expects an integer as its second parameter, found [" + nPrecision + "]"); return ExcludeFromOutputValue.Singleton; } if (toRound is NumberWithUnitValue) { var wUnit = (NumberWithUnitValue)toRound; return new NumberWithUnitValue(decimal.Round(wUnit.Value, (int)nPrecision, MidpointRounding.AwayFromZero), wUnit.Unit); } var woUnit = (NumberValue)toRound; return new NumberValue(decimal.Round(woUnit.Value, (int)nPrecision, MidpointRounding.AwayFromZero)); }
private static void TryMinifyNumberWithUnit(NumberWithUnitValue value, ReadOnlyDictionary<Unit, decimal> possibleConversions, ref NumberWithUnitValue smallest) { if (!possibleConversions.ContainsKey(value.Unit)) return; var min = MinifyNumberValue(value); var ret = new NumberWithUnitValue(min.Value, value.Unit); string retStr; using (var buffer = new StringWriter()) { ret.Write(buffer); retStr = buffer.ToString(); } var inBasic = min.Value * possibleConversions[value.Unit]; foreach (var unit in possibleConversions.Keys) { var conversion = possibleConversions[unit]; var maxPrecision = inBasic / conversion; // 5 decimal points seems like an acceptable level of precision; webkit seems to agree var inUnit = decimal.Round(maxPrecision, 5); var asNum = new NumberValue(inUnit); var minified = MinifyNumberValue(asNum); var newMin = new NumberWithUnitValue(minified.Value, unit); string newMinStr; using (var buffer = new StringWriter()) { newMin.Write(buffer); newMinStr = buffer.ToString(); } if (newMinStr.Length < retStr.Length) { ret = newMin; retStr = newMinStr; } } smallest = ret; }
public static Value Gray(IEnumerable<Value> parameters, IPosition position) { if (parameters.Count() != 1) { Current.RecordError(ErrorType.Compiler, position, "Gray expects 1 color parameter"); return ExcludeFromOutputValue.Singleton; } var param = parameters.ElementAt(0); if (param is ExcludeFromOutputValue) return ExcludeFromOutputValue.Singleton; if (param is NotFoundValue) return NotFoundValue.Default.BindToPosition(position.Start, position.Start, position.FilePath); if (!(param is ColorValue)) { Current.RecordError(ErrorType.Compiler, position, "Gray expects a color value, found [" + param + "]"); return ExcludeFromOutputValue.Singleton; } var parts = ConvertToRGB((ColorValue)param, position); if (parts == null) return ExcludeFromOutputValue.Singleton; var newPart = new NumberValue(decimal.Round((parts.Item1 + parts.Item2 + parts.Item3) / 3.0m, 2)); if(param is RGBAColorValue) { var alpha = ((RGBAColorValue)param).Alpha; // Need to keep the alpah component in this case return new RGBAColorValue(newPart, newPart, newPart, alpha); } return new RGBColorValue(newPart, newPart, newPart); }
private static NumberValue MinifyNumberValue(NumberValue value) { var asStr = value.Value.ToString(); if (asStr.Contains('.')) { asStr = asStr.TrimEnd('0'); asStr = asStr.TrimEnd('.'); } asStr = asStr.TrimStart('0'); if (asStr.Length == 0) asStr = "0"; return new NumberValue(decimal.Parse(asStr)); }