in AjaxMinDll/Css/CssParser.cs [2953:3158]
private Parsed ParseRgb()
{
var parsed = Parsed.False;
if (CurrentTokenType == TokenType.Function
&& string.Compare(CurrentTokenText, "rgb(", StringComparison.OrdinalIgnoreCase) == 0)
{
// rgb function parsing
var useRGB = false;
var crunchedRGB = false;
// converting to #rrggbb or #rgb IF we don't find any significant comments!
// skip any space or comments
var rgb = new int[3];
// we're going to be building up the rgb function just in case we need it
var sbRGB = StringBuilderPool.Acquire();
try
{
sbRGB.Append(CurrentTokenText.ToLowerInvariant());
var comments = NextSignificantToken();
if (comments.Length > 0)
{
// add the comments
sbRGB.Append(comments);
// and signal that we need to use the RGB function because of them
useRGB = true;
}
for (var ndx = 0; ndx < 3; ++ndx)
{
// if this isn't the first number, we better find a comma separator
if (ndx > 0)
{
if (CurrentTokenType == TokenType.Character && CurrentTokenText == ",")
{
// add it to the rgb string builder
sbRGB.Append(',');
}
else if (CurrentTokenType == TokenType.Character && CurrentTokenText == ")")
{
ReportError(0, CssErrorCode.ExpectedComma, CurrentTokenText);
// closing paren is the end of the function! exit the loop
useRGB = true;
break;
}
else
{
ReportError(0, CssErrorCode.ExpectedComma, CurrentTokenText);
sbRGB.Append(CurrentTokenText);
useRGB = true;
}
// skip to the next significant
comments = NextSignificantToken();
if (comments.Length > 0)
{
// add the comments
sbRGB.Append(comments);
// and signal that we need to use the RGB function because of them
useRGB = true;
}
}
// although we ALLOW negative numbers here, we'll trim them
// later. But in the mean time, save a negation flag.
var negateNumber = false;
if (CurrentTokenType == TokenType.Character && CurrentTokenText == "-")
{
negateNumber = true;
comments = NextSignificantToken();
if (comments.Length > 0)
{
// add the comments
sbRGB.Append(comments);
// and signal that we need to use the RGB function because of them
useRGB = true;
}
}
// we might adjust the value, so save the token text
var tokenText = CurrentTokenText;
if (CurrentTokenType != TokenType.Number && CurrentTokenType != TokenType.Percentage)
{
ReportError(0, CssErrorCode.ExpectedRgbNumberOrPercentage, CurrentTokenText);
useRGB = true;
}
else
{
if (CurrentTokenType == TokenType.Number)
{
// get the number value
float numberValue;
if (tokenText.TryParseSingleInvariant(out numberValue))
{
numberValue *= (negateNumber ? -1 : 1);
// make sure it's between 0 and 255
if (numberValue < 0)
{
tokenText = "0";
rgb[ndx] = 0;
}
else if (numberValue > 255)
{
tokenText = "255";
rgb[ndx] = 255;
}
else
{
rgb[ndx] = System.Convert.ToInt32(numberValue);
}
}
else
{
// error -- not even a number. Keep the rgb function
// (and don't change the token)
useRGB = true;
}
}
else
{
// percentage
float percentageValue;
if (tokenText.Substring(0, tokenText.Length - 1).TryParseSingleInvariant(out percentageValue))
{
percentageValue *= (negateNumber ? -1 : 1);
if (percentageValue < 0)
{
tokenText = "0%";
rgb[ndx] = 0;
}
else if (percentageValue > 100)
{
tokenText = "100%";
rgb[ndx] = 255;
}
else
{
rgb[ndx] = System.Convert.ToInt32(percentageValue * 255 / 100);
}
}
else
{
// error -- not even a number. Keep the rgb function
// (and don't change the token)
useRGB = true;
}
}
}
// add the number to the rgb string builder
sbRGB.Append(tokenText);
// skip to the next significant
comments = NextSignificantToken();
if (comments.Length > 0)
{
// add the comments
sbRGB.Append(comments);
// and signal that we need to use the RGB function because of them
useRGB = true;
}
}
if (useRGB)
{
// something prevented us from collapsing the rgb function
// just output the rgb function we've been building up
Append(sbRGB.ToString());
}
else
{
// we can collapse it to either #rrggbb or #rgb
// calculate the full hex string and crunch it
var fullCode = "#{0:x2}{1:x2}{2:x2}".FormatInvariant(rgb[0], rgb[1], rgb[2]);
var hexString = CrunchHexColor(fullCode, Settings.ColorNames, m_noColorAbbreviation);
Append(hexString);
// set the flag so we know we don't want to add the closing paren
crunchedRGB = true;
}
}
finally
{
sbRGB.Release();
}
if (CurrentTokenType == TokenType.Character && CurrentTokenText == ")")
{
if (!crunchedRGB)
{
AppendCurrent();
}
SkipSpace();
parsed = Parsed.True;
}
else
{
ReportError(0, CssErrorCode.ExpectedClosingParenthesis, CurrentTokenText);
}
}
return parsed;
}