/// <summary> /// Tries to parse a colour from the css value. Returns true if successful, otherwise false. /// </summary> /// <param name="part"></param> /// <param name="color"></param> /// <returns></returns> public static bool ParseCSSColor(string part, out PDFColor color, out double?opacity) { bool result = false; color = null; opacity = null; if (string.IsNullOrEmpty(part) == false) { string hexValue; if (CSSColors.Names2Colors.TryGetValue(part, out hexValue)) { result = PDFColor.TryParse(hexValue, out color); } else if (part.StartsWith("#")) { result = PDFColor.TryParse(part, out color); } else if (part.StartsWith("rgb(", StringComparison.InvariantCultureIgnoreCase)) { result = PDFColor.TryParse(part, out color); } else if (part.StartsWith("rgba(", StringComparison.InvariantCultureIgnoreCase)) { result = PDFColor.TryParseRGBA(part, out color, out opacity); } } return(result); }
protected override object DoGetNativeValue(string key, string qsValue, IPDFComponent comp) { PDFColor val; if (string.IsNullOrEmpty(qsValue) || !PDFColor.TryParse(qsValue, out val)) { val = this.Value; } return(val); }
protected override void DoSetNativeValueFromString(string value, IPDFComponent owner) { PDFColor val; if (string.IsNullOrEmpty(value)) { this.Value = PDFColor.Transparent; } else if (PDFColor.TryParse(value, out val)) { this.Value = val; } else { throw new InvalidCastException("Could not parse the value '" + value + "' to a PDFColor"); } }
private IExpression CompileExpression(Queue <Token> tokens, OperatorPrecedence minimumPrecedence, IList <string> variables, bool isWithinFunction) { if (tokens is null) { throw new ArgumentNullException(nameof(tokens), "You must call Tokenise before compiling"); } IExpression leftHandSide = null; var currentToken = tokens.PeekOrDefault(); Token previousToken = null; while (currentToken != null) { if (this.context.TryGetOperator(currentToken.CurrentToken, out var op)) // Are we an IOperator? { var precedence = op.GetPrecedence(previousToken); if (precedence > minimumPrecedence) { tokens.Dequeue(); if (!op.CanGetCaptiveTokens(previousToken, currentToken, tokens)) { // Do it anyway to update the list of tokens op.GetCaptiveTokens(previousToken, currentToken, tokens); break; } IExpression rightHandSide = null; var captiveTokens = op.GetCaptiveTokens(previousToken, currentToken, tokens); if (captiveTokens.Length > 1) { var innerTokens = op.GetInnerCaptiveTokens(captiveTokens); rightHandSide = this.CompileExpression(new Queue <Token>(innerTokens), OperatorPrecedence.Minimum, variables, isWithinFunction); currentToken = captiveTokens[captiveTokens.Length - 1]; } else { rightHandSide = this.CompileExpression(tokens, precedence, variables, isWithinFunction); // We are at the end of an expression so fake it up. currentToken = new Token(")", -1, ExpressionTokenType.Parenthese); } leftHandSide = op.BuildExpression(previousToken, new[] { leftHandSide, rightHandSide }, this.context); } else { break; } } else if (this.TryGetConstant(currentToken.CurrentToken, out var constant)) { CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); tokens.Dequeue(); leftHandSide = constant; } else if (this.context.TryGetFunction(currentToken.CurrentToken, out var function)) // or an IFunction? { CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); var expressions = new List <IExpression>(); var captiveTokens = new Queue <Token>(); var parenCount = 0; tokens.Dequeue(); // Loop through the list of tokens and split by ParameterSeparator character while (tokens.Count > 0) { var nextToken = tokens.Dequeue(); if (string.Equals(nextToken.CurrentToken, "(", StringComparison.Ordinal)) { parenCount++; } else if (string.Equals(nextToken.CurrentToken, ")", StringComparison.Ordinal)) { parenCount--; } if (!(parenCount == 1 && nextToken.CurrentToken == "(") && !(parenCount == 0 && nextToken.CurrentToken == ")")) { captiveTokens.Enqueue(nextToken); } if (parenCount == 0 && captiveTokens.Any()) { expressions.Add(this.CompileExpression(captiveTokens, minimumPrecedence: OperatorPrecedence.Minimum, variables: variables, isWithinFunction: true)); captiveTokens.Clear(); } else if (string.Equals(nextToken.CurrentToken, Context.ParameterSeparator.ToString(), StringComparison.Ordinal) && parenCount == 1) { // TODO: Should we expect expressions to be null??? expressions.Add(this.CompileExpression(captiveTokens, minimumPrecedence: 0, variables: variables, isWithinFunction: true)); captiveTokens.Clear(); } if (parenCount <= 0) { break; } } leftHandSide = new FunctionExpression(currentToken.CurrentToken, function, context, expressions.ToArray()); } else if (currentToken.CurrentToken.IsNumeric(this.context.DecimalCurrentCulture)) // Or a number { CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); tokens.Dequeue(); if (int.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.context.DecimalCurrentCulture, out var intValue)) { leftHandSide = new ConstantValueExpression(intValue); } else if (decimal.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.context.DecimalCurrentCulture, out var decimalValue)) { leftHandSide = new ConstantValueExpression(decimalValue); } else if (double.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.context.DecimalCurrentCulture, out var doubleValue)) { leftHandSide = new ConstantValueExpression(doubleValue); } else if (float.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.context.DecimalCurrentCulture, out var floatValue)) { leftHandSide = new ConstantValueExpression(floatValue); } else if (long.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.context.DecimalCurrentCulture, out var longValue)) { leftHandSide = new ConstantValueExpression(longValue); } } else if (currentToken.CurrentToken.StartsWith("[") && currentToken.CurrentToken.EndsWith("]")) // or a variable? { tokens.Dequeue(); var variableName = currentToken.CurrentToken.Replace("[", "").Replace("]", ""); CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); leftHandSide = CreateVariableExpression(variableName, this.context); if (!variables.Contains(variableName, this.context.ParsingStringComparer)) { variables.Add(variableName); } } else if (currentToken.CurrentToken.StartsWith("{") && currentToken.CurrentToken.EndsWith("}")) // or a variable? { tokens.Dequeue(); var variableName = currentToken.CurrentToken.Replace("{", "").Replace("}", ""); CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); leftHandSide = CreateVariableExpression(variableName, this.context); if (!variables.Contains(variableName, this.context.ParsingStringComparer)) { variables.Add(variableName); } } else if (currentToken.Type == ExpressionTokenType.Color) { PDFColor color; tokens.Dequeue(); if (!PDFColor.TryParse(currentToken.CurrentToken, out color)) { throw new UnrecognisedTokenException(currentToken.CurrentToken); } else { leftHandSide = new ConstantValueExpression(color); } } else if (currentToken.Type == ExpressionTokenType.Unit) { PDFUnit unit; tokens.Dequeue(); if (!PDFUnit.TryParse(currentToken.CurrentToken, out unit)) { throw new UnrecognisedTokenException(currentToken.CurrentToken); } else { leftHandSide = new ConstantValueExpression(unit); } } else if (currentToken.CurrentToken.StartsWith(Context.DateSeparator.ToString()) && currentToken.CurrentToken.EndsWith(Context.DateSeparator.ToString())) // or a date? { CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); tokens.Dequeue(); var dateToken = currentToken.CurrentToken.Replace(Context.DateSeparator.ToString(), ""); // If we can't parse the date let's check for some known tags. if (!DateTime.TryParse(dateToken, out var date)) { if (string.Equals("TODAY", dateToken, StringComparison.OrdinalIgnoreCase)) { date = DateTime.Today; } else if (string.Equals("NOW", dateToken, StringComparison.OrdinalIgnoreCase)) { date = DateTime.Now; } else { throw new UnrecognisedTokenException(dateToken); } } leftHandSide = new ConstantValueExpression(date); } else if ((currentToken.CurrentToken.StartsWith("'") && currentToken.CurrentToken.EndsWith("'")) || (currentToken.CurrentToken.StartsWith("\"") && currentToken.CurrentToken.EndsWith("\""))) { CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction); tokens.Dequeue(); leftHandSide = new ConstantValueExpression(CleanString(currentToken.CurrentToken.Substring(1, currentToken.Length - 2))); } else if (string.Equals(currentToken.CurrentToken, Context.ParameterSeparator.ToString(), StringComparison.Ordinal)) // Make sure we ignore the parameter separator { if (!isWithinFunction) { throw new ExpressiveException("Unexpected parameter separator token '" + Context.ParameterSeparator + "' or unnrecognised outer function."); } tokens.Dequeue(); } else { tokens.Dequeue(); throw new UnrecognisedTokenException(currentToken.CurrentToken); } previousToken = currentToken; currentToken = tokens.PeekOrDefault(); } return(leftHandSide); }