internal bool ParseHSLColor(ref nscolor aColor, char aStop) { float h = 0, s = 0, l = 0; // Get the hue if (!GetToken(true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEColorHueEOF"); }; return false; } if (mToken.mType != nsCSSTokenType.Number) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEExpectedNumber", mToken); }; UngetToken(); return false; } h = mToken.mNumber; h /= 360.0f; // hue values are wraparound h = h - (float)Math.Floor(h); if (!ExpectSymbol(',', true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEExpectedComma", mToken); }; return false; } // Get the saturation if (!GetToken(true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEColorSaturationEOF"); }; return false; } if (mToken.mType != nsCSSTokenType.Percentage) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEExpectedPercent", mToken); }; UngetToken(); return false; } s = mToken.mNumber; if (s < 0.0f) s = 0.0f; if (s > 1.0f) s = 1.0f; if (!ExpectSymbol(',', true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEExpectedComma", mToken); }; return false; } // Get the lightness if (!GetToken(true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEColorLightnessEOF"); }; return false; } if (mToken.mType != nsCSSTokenType.Percentage) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEExpectedPercent", mToken); }; UngetToken(); return false; } l = mToken.mNumber; if (l < 0.0f) l = 0.0f; if (l > 1.0f) l = 1.0f; if (ExpectSymbol(aStop, true)) { aColor = nscolor.HSL2RGB(h, s, l); return true; } { if (!mSuppressErrors) mReporter.ReportUnexpected("PEColorComponentBadTerm", mToken, aStop); }; return false; }
// The types to pass to ParseColorComponent. These correspond to the // various datatypes that can go within rgb(). internal bool ParseColor(ref nsCSSValue aValue) { if (!GetToken(true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEColorEOF"); }; return false; } nsCSSToken tk = mToken; var rgba = new nscolor(); switch (tk.mType) { case nsCSSTokenType.ID: case nsCSSTokenType.Hash: // #xxyyzz if (nscolor.HexToRGB(tk.mIdentStr, ref rgba)) { aValue.SetColorValue(rgba); return true; } break; case nsCSSTokenType.Ident: if (nscolor.ColorNameToRGB(tk.mIdentStr, ref rgba)) { aValue.SetStringValue(tk.mIdentStr, nsCSSUnit.Ident); return true; } else { nsCSSKeyword keyword = nsCSSKeywords.LookupKeyword(tk.mIdentStr); if (nsCSSKeyword.UNKNOWN < keyword) { // known keyword int32_t value = 0; if (nsCSSProps.FindKeyword(keyword, nsCSSProps.kColorKTable, ref value)) { aValue.SetIntValue(value, nsCSSUnit.EnumColor); return true; } } } break; case nsCSSTokenType.Function: if (mToken.mIdentStr.LowerCaseEqualsLiteral("rgb")) { // rgb ( component , component , component ) uint8_t r = 0, g = 0, b = 0; int32_t type = COLOR_TYPE_UNKNOWN; if (ParseColorComponent(ref r, ref type, ',') && ParseColorComponent(ref g, ref type, ',') && ParseColorComponent(ref b, ref type, ')')) { aValue.SetColorValue(nscolor.RGB(r,g,b)); return true; } SkipUntil(')'); return false; } else if (mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-rgba") || mToken.mIdentStr.LowerCaseEqualsLiteral("rgba")) { // rgba ( component , component , component , opacity ) uint8_t r = 0, g = 0, b = 0, a = 0; int32_t type = COLOR_TYPE_UNKNOWN; if (ParseColorComponent(ref r, ref type, ',') && ParseColorComponent(ref g, ref type, ',') && ParseColorComponent(ref b, ref type, ',') && ParseColorOpacity(ref a)) { aValue.SetColorValue(nscolor.RGBA(r, g, b, a)); return true; } SkipUntil(')'); return false; } else if (mToken.mIdentStr.LowerCaseEqualsLiteral("hsl")) { // hsl ( hue , saturation , lightness ) // "hue" is a number, "saturation" and "lightness" are percentages. if (ParseHSLColor(ref rgba, ')')) { aValue.SetColorValue(rgba); return true; } SkipUntil(')'); return false; } else if (mToken.mIdentStr.LowerCaseEqualsLiteral("-moz-hsla") || mToken.mIdentStr.LowerCaseEqualsLiteral("hsla")) { // hsla ( hue , saturation , lightness , opacity ) // "hue" is a number, "saturation" and "lightness" are percentages, // "opacity" is a number. uint8_t a = 0; if (ParseHSLColor(ref rgba, ',') && ParseColorOpacity(ref a)) { aValue.SetColorValue(nscolor.RGBA(rgba.R, rgba.G, rgba.B, a)); return true; } SkipUntil(')'); return false; } break; default: break; } // try 'xxyyzz' without '#' prefix for compatibility with IE and Nav4x (bug 23236 and 45804) // TODO support hashless colors // It's not a color { if (!mSuppressErrors) mReporter.ReportUnexpected("PEColorNotColor", mToken); }; UngetToken(); return false; }